diff --git a/.gitignore b/.gitignore index 55ccd32..caa32e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,2 @@ .idea/ -*.iml -### yml ### -application.yml - - -.env - -.vscode \ No newline at end of file +*.iml \ No newline at end of file diff --git a/README.md b/README.md index 0e493d9..b7a35ad 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,3 @@ | | | | | | | 윤민섭 | 김혜림 | 박채연 | 박세웅 | 김민주 | | [Minsub](https://github.com/minsubyun1) | [kimhyerim01](https://github.com/kimhyerim01) | [yeonchaepark](https://github.com/yeonchaepark) | [hardwoong](https://github.com/hardwoong) | [calla1102](https://github.com/calla1102) | - diff --git a/retrigger.txt b/retrigger.txt deleted file mode 100644 index ab6a307..0000000 --- a/retrigger.txt +++ /dev/null @@ -1,2 +0,0 @@ -// retrigger CI after base branch change -//ABCD CI after base branch change diff --git a/server/.gitignore b/server/.gitignore index a063734..c2065bc 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -35,7 +35,3 @@ out/ ### VS Code ### .vscode/ - - -### yml -application.yml \ No newline at end of file diff --git a/server/build.gradle b/server/build.gradle index 30bb27d..5116a3f 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -27,23 +27,12 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' - implementation("io.jsonwebtoken:jjwt-api:0.12.4") - implementation 'org.springframework.boot:spring-boot-starter-security' - runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.4") - runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.4") compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - - implementation 'io.jsonwebtoken:jjwt-api:0.11.5' - runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' - runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' - implementation 'io.github.cdimascio:dotenv-java:3.0.0' - implementation 'me.paulschwarz:spring-dotenv:4.0.0' } tasks.named('test') { diff --git a/server/src/main/java/com/soopgyeol/api/common/dto/NicknameUpdateRequest.java b/server/src/main/java/com/soopgyeol/api/common/dto/NicknameUpdateRequest.java deleted file mode 100644 index ecdf725..0000000 --- a/server/src/main/java/com/soopgyeol/api/common/dto/NicknameUpdateRequest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soopgyeol.api.common.dto; - -import jakarta.validation.constraints.Pattern; -import jakarta.validation.constraints.Size; -import lombok.Getter; - -@Getter -public class NicknameUpdateRequest { - @Size(min = 2, max = 12, message = "닉네임은 2자 이상 12자 이하로 입력해주세요.") - @Pattern(regexp = ".*[a-zA-Z가-힣]+.*", message = "닉네임에는 한글 또는 영문자가 최소 1자 이상 포함되어야 합니다.") - private String nickname; - -} diff --git a/server/src/main/java/com/soopgyeol/api/common/dto/NicknameUpdateResponse.java b/server/src/main/java/com/soopgyeol/api/common/dto/NicknameUpdateResponse.java deleted file mode 100644 index 3260ca0..0000000 --- a/server/src/main/java/com/soopgyeol/api/common/dto/NicknameUpdateResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.soopgyeol.api.common.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; - -@Data -@AllArgsConstructor -public class NicknameUpdateResponse { - private String nickname; -} diff --git a/server/src/main/java/com/soopgyeol/api/common/exception/InsufficientBalanceException.java b/server/src/main/java/com/soopgyeol/api/common/exception/InsufficientBalanceException.java deleted file mode 100644 index c255b86..0000000 --- a/server/src/main/java/com/soopgyeol/api/common/exception/InsufficientBalanceException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.soopgyeol.api.common.exception; - -public class InsufficientBalanceException extends RuntimeException { - public InsufficientBalanceException(String message) { - super(message); - } -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/common/exception/ItemAlreadyOwnedException.java b/server/src/main/java/com/soopgyeol/api/common/exception/ItemAlreadyOwnedException.java deleted file mode 100644 index b76ee63..0000000 --- a/server/src/main/java/com/soopgyeol/api/common/exception/ItemAlreadyOwnedException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soopgyeol.api.common.exception; - -public class ItemAlreadyOwnedException extends RuntimeException { - public ItemAlreadyOwnedException(String message) { - super(message); - } -} - diff --git a/server/src/main/java/com/soopgyeol/api/config/DevDataInitializer.java b/server/src/main/java/com/soopgyeol/api/config/DevDataInitializer.java deleted file mode 100644 index 71f0234..0000000 --- a/server/src/main/java/com/soopgyeol/api/config/DevDataInitializer.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.soopgyeol.api.config; - -import com.soopgyeol.api.domain.user.Role; -import com.soopgyeol.api.domain.user.SocialLoginType; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.repository.UserRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -import org.springframework.boot.CommandLineRunner; - -@Component -@RequiredArgsConstructor -public class DevDataInitializer implements CommandLineRunner{ - - private final UserRepository userRepository; - - @Override - public void run(String... args) { - if(userRepository.count() == 0) { - User testUser = User.builder() - .nickname("테스트 유저") - .email("test@example.com") - .password("1234") - .role(Role.USER) - .provider(SocialLoginType.GOOGLE) - .build(); - - userRepository.save(testUser); - - System.out.println("테스트 유저가 자동 등록되었습니다. ID: " + testUser.getId()); - } - } -} diff --git a/server/src/main/java/com/soopgyeol/api/config/DotEnvConfig.java b/server/src/main/java/com/soopgyeol/api/config/DotEnvConfig.java deleted file mode 100644 index 72fcd69..0000000 --- a/server/src/main/java/com/soopgyeol/api/config/DotEnvConfig.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soopgyeol.api.config; - -import io.github.cdimascio.dotenv.Dotenv; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class DotEnvConfig { - - @Bean - public Dotenv dotenv() { - return Dotenv.configure() - .directory(System.getProperty("user.dir")) // 👈 명확하게 루트 경로 지정 - .ignoreIfMissing() - .load(); - } -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/config/PasswordEncoderConfig.java b/server/src/main/java/com/soopgyeol/api/config/PasswordEncoderConfig.java deleted file mode 100644 index a552b09..0000000 --- a/server/src/main/java/com/soopgyeol/api/config/PasswordEncoderConfig.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soopgyeol.api.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; - -@Configuration -public class PasswordEncoderConfig { - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } -} diff --git a/server/src/main/java/com/soopgyeol/api/config/SecurityConfig.java b/server/src/main/java/com/soopgyeol/api/config/SecurityConfig.java deleted file mode 100644 index d4aaee4..0000000 --- a/server/src/main/java/com/soopgyeol/api/config/SecurityConfig.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.soopgyeol.api.config; - -import com.soopgyeol.api.service.jwt.JwtAuthFilter; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.factory.PasswordEncoderFactories; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.access.IpAddressAuthorizationManager; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; - - -@Configuration -@EnableWebSecurity -@RequiredArgsConstructor -public class SecurityConfig { - - private final JwtAuthFilter jwtAuthFilter; - - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - - http.csrf(csrf -> csrf.disable()); - - - http.sessionManagement(sm -> sm - .sessionCreationPolicy(SessionCreationPolicy.STATELESS)); - - http.authorizeHttpRequests(auth -> auth - .requestMatchers("/api/v1/auth/dev-login").permitAll() - .requestMatchers( - "/oauth2/**", - "/login/oauth2/**", - "/login-success", - "/auth/oauth2/**", - "/favicon.ico", - "/auth/login", - "/oauth2/google/code-log", - "/api/v1/auth/oauth/oauth2/**", - "/api/v1/auth/oauth/**" - ).permitAll() - .anyRequest().authenticated() - ); - - - - - - http.exceptionHandling(eh -> eh - .authenticationEntryPoint( - (req, res, ex) -> res.sendError(HttpServletResponse.SC_UNAUTHORIZED))); - - http.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); - - return http.build(); - } - - -} diff --git a/server/src/main/java/com/soopgyeol/api/config/auth/CustomUserDetails.java b/server/src/main/java/com/soopgyeol/api/config/auth/CustomUserDetails.java deleted file mode 100644 index b7d5f2e..0000000 --- a/server/src/main/java/com/soopgyeol/api/config/auth/CustomUserDetails.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.soopgyeol.api.config.auth; - - -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -import java.util.Collection; - - -public class CustomUserDetails implements UserDetails { - private final Long userId; - private final String username; - private final String password; - private final Collection authorities; - - public CustomUserDetails(Long userId, String username, String password, Collection authorities) { - this.userId = userId; - this.username = username; - this.password = password; - this.authorities = authorities; - } - - // userId getter - public Long getUserId() { - return userId; - } - - @Override - public String getUsername() { - return username; - } - - @Override - public String getPassword() { - return password; - } - - @Override - public Collection getAuthorities() { - return authorities; - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return true; - } -} diff --git a/server/src/main/java/com/soopgyeol/api/controller/AuthController.java b/server/src/main/java/com/soopgyeol/api/controller/AuthController.java deleted file mode 100644 index 2549192..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/AuthController.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.soopgyeol.api.controller; - -import com.soopgyeol.api.dto.oauth.OAuthLoginRequest; -import com.soopgyeol.api.dto.oauth.OAuthLoginResponse; -import com.soopgyeol.api.service.auth.GoogleOauth; -import com.soopgyeol.api.service.auth.KakaoOauth; -import com.soopgyeol.api.service.auth.OAuthService; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; -import java.util.Map; - -//임시 토큰 코드 사용 시 활성화 -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.repository.UserRepository; -import com.soopgyeol.api.service.jwt.JwtProvider; -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/auth/oauth") -public class AuthController { - - private final OAuthService oAuthService; - private final GoogleOauth googleOauth; - private final KakaoOauth kakaoOauth; - - @PostMapping("/login") - public OAuthLoginResponse login(@RequestBody OAuthLoginRequest request) { - return oAuthService.login(request); - } - - @GetMapping("/oauth2/google/url") - public ResponseEntity> getGoogleLoginUrl() { - String url = googleOauth.getOauthRedirectURL(); - return ResponseEntity.ok(Map.of("url", url)); - } - - @GetMapping("/oauth2/kakao/url") - public ResponseEntity> getKakaoLoginUrl() { - String url = kakaoOauth.getOauthRedirectURL(); - return ResponseEntity.ok(Map.of("url", url)); - } - - - @GetMapping("/oauth2/google/code-log") - public void googleAutoLogin(@RequestParam String code, HttpServletResponse response) throws IOException { - // 기존 login() 재활용 - OAuthLoginRequest loginRequest = OAuthLoginRequest.builder() - .provider("GOOGLE") - .code(code) - .build(); - - OAuthLoginResponse loginResponse = oAuthService.login(loginRequest); - - // JWT 꺼내기 - String jwtToken = loginResponse.getJwtToken(); - - // 앱용 딥링크로 변경 - response.sendRedirect("soopgyeol://oauth-callback/google?token=" + jwtToken); - - } - - - - - @GetMapping("/oauth2/kakao/code-log") - public void kakaoAutoLogin(@RequestParam String code, HttpServletResponse response) throws IOException { - OAuthLoginRequest loginRequest = OAuthLoginRequest.builder() - .provider("KAKAO") - .code(code) - .build(); - - OAuthLoginResponse loginResponse = oAuthService.login(loginRequest); - - String jwtToken = loginResponse.getJwtToken(); - - // 앱 용 딥링크로 변경 - response.sendRedirect("soopgyeol://oauth-callback/kakao?token=" + jwtToken); - } - - - - - // 임시 토큰 생성시 활성화 - private final UserRepository userRepository; - private final JwtProvider jwtProvider; - @PostMapping("/dev-login") - public OAuthLoginResponse devLogin(@RequestParam Long userId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("유저 없음")); - - String jwt = jwtProvider.createToken(user.getId(), user.getRole()); - - return OAuthLoginResponse.builder() - .jwtToken(jwt) - .isNewUser(false) - .build(); - } - - -} diff --git a/server/src/main/java/com/soopgyeol/api/controller/BuyController.java b/server/src/main/java/com/soopgyeol/api/controller/BuyController.java deleted file mode 100644 index d9f940e..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/BuyController.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.soopgyeol.api.controller; - -import com.soopgyeol.api.domain.buy.dto.*; -import com.soopgyeol.api.service.jwt.JwtProvider; -import com.soopgyeol.api.service.buy.BuyService; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@RestController -@RequestMapping("/items/buy") -@RequiredArgsConstructor -public class BuyController { - - private final BuyService buyService; - private final JwtProvider jwtProvider; - - @PostMapping - public ResponseEntity buyItem(@RequestHeader("Authorization") String authorizationHeader, - @RequestBody BuyRequest request) { - String token = authorizationHeader.replace("Bearer ", ""); - Long userId = jwtProvider.getUserId(token); - - BuyResult result = buyService.buyItem(userId, request.getItemId()); - - BuyResponse response = BuyResponse.builder() - .itemId(result.getItemId()) - .itemName(result.getItemName()) - .itemPrice(result.getItemPrice()) - .userMoneyBalance(result.getUserMoneyBalance()) - .message("구매가 완료되었습니다.") - .build(); - - return ResponseEntity.ok(response); - } -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/controller/CarbonItemController.java b/server/src/main/java/com/soopgyeol/api/controller/CarbonItemController.java deleted file mode 100644 index df3883d..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/CarbonItemController.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.soopgyeol.api.controller; - -import com.soopgyeol.api.common.dto.ApiResponse; -import com.soopgyeol.api.domain.carbon.dto.CarbonAnalysisRequest; -import com.soopgyeol.api.domain.carbon.dto.CarbonAnalysisResponse; -import com.soopgyeol.api.domain.challenge.dto.AIChallengeSendingRequest; -import com.soopgyeol.api.service.carbon.CarbonAnalysisService; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.soopgyeol.api.config.auth.CustomUserDetails; -import org.springframework.security.core.annotation.AuthenticationPrincipal; - -@RestController -@RequestMapping("/carbon") -@RequiredArgsConstructor -public class CarbonItemController { - - private final CarbonAnalysisService carbonAnalysisService; - - @PostMapping("/analyze") - public ResponseEntity> analyzeCarbon( - @RequestBody CarbonAnalysisRequest request) { - CarbonAnalysisResponse response = carbonAnalysisService.analyzeAndSave(request.getUserInput()); - return ResponseEntity.ok(new ApiResponse<>(true, "검색 성공", response)); - } - - - @PostMapping("/analyze/keyword") - public ResponseEntity> analyzeByKeyword(@RequestBody AIChallengeSendingRequest request) { - CarbonAnalysisResponse response = carbonAnalysisService.analyzeByKeyword(request.getKeyword(), request.getCategory(), request.getChallengeId()); // 저장 없이 반환 - return ResponseEntity.ok(new ApiResponse<>(true, "챌린지 기반 검색 성공", response)); - } -} diff --git a/server/src/main/java/com/soopgyeol/api/controller/DailyChallengeController.java b/server/src/main/java/com/soopgyeol/api/controller/DailyChallengeController.java deleted file mode 100644 index 4b566cb..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/DailyChallengeController.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.soopgyeol.api.controller; - -import com.soopgyeol.api.common.dto.ApiResponse; -import com.soopgyeol.api.config.auth.CustomUserDetails; -import com.soopgyeol.api.domain.challenge.dto.ChallengeCompleteRequest; -import com.soopgyeol.api.domain.challenge.dto.ChallengeCompleteResponse; -import com.soopgyeol.api.domain.challenge.dto.ChallengeTodayResponse; -import com.soopgyeol.api.domain.challenge.dto.UserChallengeHistoryDto; -import com.soopgyeol.api.service.dailychallenge.UserChallengeServiceImpl; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@RestController -@RequestMapping("/challenges") -@RequiredArgsConstructor -public class DailyChallengeController { - private final UserChallengeServiceImpl userChallengeService; - - @GetMapping("/today") - public ResponseEntity> getOrCreateTodayChallenge ( - @AuthenticationPrincipal CustomUserDetails userDetails - ){ - ChallengeTodayResponse dto = userChallengeService.getTodayChallengeForUser(userDetails.getUserId()); - return ResponseEntity.ok(new ApiResponse<>(true, "오늘의 챌린지 조회 성공", dto)); - } - - @PostMapping("/complete") - public ResponseEntity> completeChallenge(@AuthenticationPrincipal CustomUserDetails userDetails, @RequestBody ChallengeCompleteRequest request){ - ChallengeCompleteResponse response = userChallengeService.completeChallenge(userDetails.getUserId(), request.getDailyChallengeId()); - return ResponseEntity.ok(new ApiResponse<>(true, "챌린지 포인트 지급 완료", response)); - } - - @GetMapping("/history") - public ResponseEntity>> getChallengeHistory( - @AuthenticationPrincipal CustomUserDetails userDetails - ) { - List history = userChallengeService.getUserChallengeHistory(userDetails.getUserId()); - return ResponseEntity.ok(new ApiResponse<>(true, "챌린지 수행 이력 조회 성공", history)); - } - - -} diff --git a/server/src/main/java/com/soopgyeol/api/controller/HeroStageController.java b/server/src/main/java/com/soopgyeol/api/controller/HeroStageController.java deleted file mode 100644 index a8b4b31..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/HeroStageController.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.soopgyeol.api.controller; - -import com.soopgyeol.api.common.dto.ApiResponse; -import com.soopgyeol.api.domain.stage.dto.HeroStageResponse; -import com.soopgyeol.api.service.hero.HeroStageService; -import com.soopgyeol.api.config.auth.CustomUserDetails; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -public class HeroStageController { - - private final HeroStageService heroStageService; - - @GetMapping("/hero-stage") - public ResponseEntity> getHeroStageMessage( - @AuthenticationPrincipal CustomUserDetails userDetails) { - try { - HeroStageResponse response = heroStageService.getHeroStageMessage(userDetails.getUserId()); - return ResponseEntity.ok(new ApiResponse<>(true, "영웅 단계 메시지 조회 성공", response)); - } catch (IllegalArgumentException e) { - return ResponseEntity.badRequest().body(new ApiResponse<>(false, e.getMessage(), null)); - } - } -} diff --git a/server/src/main/java/com/soopgyeol/api/controller/ItemController.java b/server/src/main/java/com/soopgyeol/api/controller/ItemController.java deleted file mode 100644 index 596c9cb..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/ItemController.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.soopgyeol.api.controller; - -import com.soopgyeol.api.common.dto.ApiResponse; -import com.soopgyeol.api.domain.enums.ItemCategory; -import com.soopgyeol.api.domain.item.dto.ItemResponse; -import com.soopgyeol.api.domain.item.dto.DisplayResponse; -import com.soopgyeol.api.service.item.ItemService; -import com.soopgyeol.api.config.auth.CustomUserDetails; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; - -@RestController -@RequiredArgsConstructor -public class ItemController { - private final ItemService itemService; - - @GetMapping("/items/category/{category}") - public ResponseEntity>> getItemsByUserAndCategory( - @AuthenticationPrincipal CustomUserDetails userDetails, - @PathVariable ItemCategory category) { - List items = itemService.getItemsByUserIdAndCategory(userDetails.getUserId(), category); - return ResponseEntity.ok(new ApiResponse<>(true, "유저별 카테고리별 아이템 조회 성공", items)); - } - - @GetMapping("/items/displayed") - public ResponseEntity>> getDisplayedItemsByUser( - @AuthenticationPrincipal CustomUserDetails userDetails) { - List items = itemService.getDisplayedItemsByUserId(userDetails.getUserId()); - return ResponseEntity.ok(new ApiResponse<>(true, "유저의 전시 아이템 조회 성공", items)); - } - - @GetMapping("/items/inventory/category/{category}") - public ResponseEntity>> getBuyedItemsByUserAndCategory( - @AuthenticationPrincipal CustomUserDetails userDetails, - @PathVariable ItemCategory category) { - List items = itemService.getBuyedItemsByUserIdAndCategory(userDetails.getUserId(), category); - return ResponseEntity.ok(new ApiResponse<>(true, "유저의 카테고리별 인벤토리(보유 아이템) 조회 성공", items)); - } - - @PatchMapping("/items/item/{itemId}/display") - public ResponseEntity> toggleDisplay( - @AuthenticationPrincipal CustomUserDetails userDetails, - @PathVariable Long itemId) { - try { - DisplayResponse response = itemService.toggleDisplay(userDetails.getUserId(), itemId); - return ResponseEntity.ok(new ApiResponse<>(true, "전시 상태 변경 성공", response)); - } catch (IllegalStateException e) { - return ResponseEntity.status(409).body(new ApiResponse<>(false, e.getMessage(), null)); - } catch (IllegalArgumentException e) { - return ResponseEntity.badRequest().body(new ApiResponse<>(false, e.getMessage(), null)); - } - } -} diff --git a/server/src/main/java/com/soopgyeol/api/controller/LoginSuccessController.java b/server/src/main/java/com/soopgyeol/api/controller/LoginSuccessController.java deleted file mode 100644 index 19c30b8..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/LoginSuccessController.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soopgyeol.api.controller; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class LoginSuccessController { - - @GetMapping("/login-success") - public String loginSuccess() { - return "구글 로그인 성공했습니다."; - } -} diff --git a/server/src/main/java/com/soopgyeol/api/controller/TreeStageController.java b/server/src/main/java/com/soopgyeol/api/controller/TreeStageController.java deleted file mode 100644 index 99bef86..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/TreeStageController.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.soopgyeol.api.controller; - -import com.soopgyeol.api.common.dto.ApiResponse; -import com.soopgyeol.api.domain.stage.dto.TreeStageResponse; -import com.soopgyeol.api.service.stage.TreeStageService; -import com.soopgyeol.api.config.auth.CustomUserDetails; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -public class TreeStageController { - - private final TreeStageService treeStageService; - - @GetMapping("/tree-stage") - public ResponseEntity> getTreeStageMessage( - @AuthenticationPrincipal CustomUserDetails userDetails) { - try { - TreeStageResponse response = treeStageService.getTreeStageMessage(userDetails.getUserId()); - return ResponseEntity.ok(new ApiResponse<>(true, "단계 메시지 조회 성공", response)); - } catch (IllegalArgumentException e) { - return ResponseEntity.badRequest().body(new ApiResponse<>(false, e.getMessage(), null)); - } - } -} diff --git a/server/src/main/java/com/soopgyeol/api/controller/UserCarbonLogController.java b/server/src/main/java/com/soopgyeol/api/controller/UserCarbonLogController.java deleted file mode 100644 index ed6a678..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/UserCarbonLogController.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.soopgyeol.api.controller; - -import com.soopgyeol.api.common.dto.ApiResponse; -import com.soopgyeol.api.config.auth.CustomUserDetails; -import com.soopgyeol.api.domain.usercarbonlog.dto.UserCarbonLogRequest; -import com.soopgyeol.api.domain.usercarbonlog.dto.UserCarbonLogResponse; -import com.soopgyeol.api.domain.usercarbonlog.dto.UserCarbonLogSummaryResponse; -import com.soopgyeol.api.service.carbonlog.UserCarbonLogService; -import lombok.RequiredArgsConstructor; -import org.springframework.format.annotation.DateTimeFormat; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import java.time.LocalDate; -import java.util.List; - -@RestController -@RequestMapping("/carbon/log") -@RequiredArgsConstructor -public class UserCarbonLogController { - private final UserCarbonLogService userCarbonLogService; - - @PostMapping - public ResponseEntity> saveLog( - @AuthenticationPrincipal CustomUserDetails userDetails, - @RequestBody UserCarbonLogRequest request) { - request.setUserId(userDetails.getUserId()); - userCarbonLogService.saveCarbonLog(request); - return ResponseEntity.ok(new ApiResponse<>(true, "탄소 소비 기록 저장 완료", null)); - } - - - @GetMapping("/daily") - public ResponseEntity> getLogsByDate( - @AuthenticationPrincipal CustomUserDetails userDetails, - @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) { - - UserCarbonLogSummaryResponse logs = userCarbonLogService.getLogsByUserIdAndDate(userDetails.getUserId(), date); - return ResponseEntity.ok(new ApiResponse<>(true, "조회 성공", logs)); - } - - @GetMapping("/daily/challenge") - public ResponseEntity> getChallengeLogsByDate( - @AuthenticationPrincipal CustomUserDetails userDetails, - @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) { - - UserCarbonLogSummaryResponse summaryResponse = userCarbonLogService.getChallengeLogsByUserIdAndDate( - userDetails.getUserId(), date - ); - - return ResponseEntity.ok(new ApiResponse<>(true, "챌린지 탄소 활동 조회 성공", summaryResponse)); - } - - -} diff --git a/server/src/main/java/com/soopgyeol/api/controller/UserController.java b/server/src/main/java/com/soopgyeol/api/controller/UserController.java deleted file mode 100644 index b8dec11..0000000 --- a/server/src/main/java/com/soopgyeol/api/controller/UserController.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.soopgyeol.api.controller; - -import com.soopgyeol.api.common.dto.NicknameUpdateRequest; -import com.soopgyeol.api.common.dto.NicknameUpdateResponse; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.domain.user.dto.UserInfoResponse; -import com.soopgyeol.api.service.UserService; -import com.soopgyeol.api.service.jwt.JwtProvider; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequestMapping("/api/v1/users") -@RequiredArgsConstructor -public class UserController { - - private final UserService userService; - private final JwtProvider jwtProvider; - - @PatchMapping("/me/nickname") - public ResponseEntity updateNickname( - @RequestHeader("Authorization") String authorizationHeader, - @Valid @RequestBody NicknameUpdateRequest request) { - - String token = authorizationHeader.replace("Bearer ", ""); - Long userId = jwtProvider.getUserId(token); - - String updatedNickname = userService.updateNickname(userId, request.getNickname()); - return ResponseEntity.ok(new NicknameUpdateResponse(updatedNickname)); - } - - @GetMapping("/me") - public ResponseEntity getMyInfo( - @RequestHeader("Authorization") String authorizationHeader) { - - String token = authorizationHeader.replace("Bearer ", ""); - Long userId = jwtProvider.getUserId(token); - - User user = userService.getUserById(userId); - - UserInfoResponse response = new UserInfoResponse( - user.getId(), - user.getEmail(), - user.getNickname()); - - return ResponseEntity.ok(response); - } - - @DeleteMapping("/me") - public ResponseEntity deleteMe(@RequestHeader("Authorization") String authorizationHeader) { - String token = authorizationHeader.replace("Bearer ", ""); - Long userId = jwtProvider.getUserId(token); - try { - userService.deleteUser(userId); - return ResponseEntity.ok().body( - java.util.Map.of( - "success", true, - "message", "회원 탈퇴 성공", - "data", userId)); - } catch (RuntimeException e) { - return ResponseEntity.status(404).body( - java.util.Map.of( - "success", false, - "message", e.getMessage(), - "data", null)); - } - } - -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/domain/buy/dto/BuyRequest.java b/server/src/main/java/com/soopgyeol/api/domain/buy/dto/BuyRequest.java deleted file mode 100644 index af8e5cd..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/buy/dto/BuyRequest.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soopgyeol.api.domain.buy.dto; - -import lombok.Getter; - -@Getter -public class BuyRequest { - private Long itemId; // 구매하려는 아이템 ID -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/buy/dto/BuyResponse.java b/server/src/main/java/com/soopgyeol/api/domain/buy/dto/BuyResponse.java deleted file mode 100644 index 1664fff..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/buy/dto/BuyResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soopgyeol.api.domain.buy.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -@AllArgsConstructor -public class BuyResponse { - private Long itemId; - private String itemName; - private int itemPrice; - private int userMoneyBalance; - private String message; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/buy/dto/BuyResult.java b/server/src/main/java/com/soopgyeol/api/domain/buy/dto/BuyResult.java deleted file mode 100644 index 56953ca..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/buy/dto/BuyResult.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soopgyeol.api.domain.buy.dto; - -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class BuyResult { - private Long itemId; - private String itemName; - private int itemPrice; - private int userMoneyBalance; -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/domain/buy/entity/Purchase.java b/server/src/main/java/com/soopgyeol/api/domain/buy/entity/Purchase.java deleted file mode 100644 index 4a30473..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/buy/entity/Purchase.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.soopgyeol.api.domain.buy.entity; - -import com.soopgyeol.api.domain.user.User; -import jakarta.persistence.*; -import lombok.*; -import com.soopgyeol.api.domain.item.entity.Item; -import org.hibernate.annotations.CreationTimestamp; -import java.time.LocalDateTime; - -@Entity -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class Purchase { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "buy_id") - private Long id; - - @ManyToOne(optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; // 구매자 (FK) - - @ManyToOne(optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "item_id") - private Item item; // 구매한 아이템 (FK) - - @Column(name = "item_money", nullable = false) - private int itemMoney; - - @CreationTimestamp - @Column(name = "purchased_at", nullable = false, updatable = false) - private LocalDateTime purchasedAt; // 구매 시각 -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/carbon/dto/CarbonAnalysisRequest.java b/server/src/main/java/com/soopgyeol/api/domain/carbon/dto/CarbonAnalysisRequest.java deleted file mode 100644 index 0d98e3b..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/carbon/dto/CarbonAnalysisRequest.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soopgyeol.api.domain.carbon.dto; - -import lombok.Data; - -@Data -public class CarbonAnalysisRequest { - private String userInput; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/carbon/dto/CarbonAnalysisResponse.java b/server/src/main/java/com/soopgyeol/api/domain/carbon/dto/CarbonAnalysisResponse.java deleted file mode 100644 index 4f33d9f..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/carbon/dto/CarbonAnalysisResponse.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.soopgyeol.api.domain.carbon.dto; - -import com.soopgyeol.api.domain.enums.Category; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class CarbonAnalysisResponse { - private Long carbonItemId; - private String name; // 상품명 - private double carbonGrams; // 탄소량 (g) - private Category category; // 카테고리 - private String categoryKorean; // 카테고리(한글) - private int growthPoint; // 단위당 성장 점수 - private String explanation; // 왜 이 정도 탄소가 나왔는지 설명 - private String categoryImageUrl; - private Long challengeId; // 챌린지 기반 검색인 경우만 -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/carbon/entity/CarbonItem.java b/server/src/main/java/com/soopgyeol/api/domain/carbon/entity/CarbonItem.java deleted file mode 100644 index 0eb7565..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/carbon/entity/CarbonItem.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.soopgyeol.api.domain.carbon.entity; - -import com.soopgyeol.api.domain.enums.Category; -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Entity -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class CarbonItem { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "carbon_item_id") - private Long id; - - @Column(nullable = false) - private String name; // 제품명 - - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private Category category; // 카테고리 - - @Column(name = "carbon_value", nullable = false) - private float carbonValue; // 단위당 탄소량 (g 기준) - - @Column(name = "growth_point", nullable = false) - private int growthPoint; - - @Column(columnDefinition = "TEXT") - private String explanation; // GPT가 제공한 탄소량 설명 - - @Column(nullable = false) - private LocalDateTime createdAt; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/AIChallengePromptResult.java b/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/AIChallengePromptResult.java deleted file mode 100644 index 7ba671f..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/AIChallengePromptResult.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soopgyeol.api.domain.challenge.dto; - -import com.soopgyeol.api.domain.enums.Category; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class AIChallengePromptResult { - private String title; - private int goalCount; - private int rewardMoney; - private String carbonKeyword; - private Category category; -} - diff --git a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/AIChallengeSendingRequest.java b/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/AIChallengeSendingRequest.java deleted file mode 100644 index 9dacbb0..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/AIChallengeSendingRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.soopgyeol.api.domain.challenge.dto; - -import com.soopgyeol.api.domain.enums.Category; -import lombok.Data; - -@Data -public class AIChallengeSendingRequest { - String keyword; - Category category; - private Long challengeId; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/ChallengeCompleteRequest.java b/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/ChallengeCompleteRequest.java deleted file mode 100644 index f6f7206..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/ChallengeCompleteRequest.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.soopgyeol.api.domain.challenge.dto; - -import lombok.Data; - -@Data -public class ChallengeCompleteRequest { - private Long userId; - private Long dailyChallengeId; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/ChallengeCompleteResponse.java b/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/ChallengeCompleteResponse.java deleted file mode 100644 index 1ac203c..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/ChallengeCompleteResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.soopgyeol.api.domain.challenge.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; - -@Data -@AllArgsConstructor -public class ChallengeCompleteResponse { - private int reward; - private int totalBalance; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/ChallengeTodayResponse.java b/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/ChallengeTodayResponse.java deleted file mode 100644 index f8d7ff6..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/ChallengeTodayResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soopgyeol.api.domain.challenge.dto; - -import com.soopgyeol.api.domain.enums.Category; -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class ChallengeTodayResponse { - private Long challengeId; - private String title; - private int goalCount; - private int rewardMoney; - private String carbonKeyword; - private Category category; - private int progressCount; - private boolean isCompleted; - private String categoryImageUrl; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/DailyChallengeResponse.java b/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/DailyChallengeResponse.java deleted file mode 100644 index 9ad93ff..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/DailyChallengeResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soopgyeol.api.domain.challenge.dto; - -import com.soopgyeol.api.domain.enums.Category; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class DailyChallengeResponse { - private Long id; - private String title; - private int goalCount; - private int rewardMoney; - private String carbonKeyword; - private Category category; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/UserChallengeHistoryDto.java b/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/UserChallengeHistoryDto.java deleted file mode 100644 index d7df902..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/challenge/dto/UserChallengeHistoryDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soopgyeol.api.domain.challenge.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; - -import java.time.LocalDate; - -@Data -@AllArgsConstructor -@Builder -public class UserChallengeHistoryDto { - private String title; - private LocalDate createdAt; - private boolean isCompleted; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/challenge/entity/DailyChallenge.java b/server/src/main/java/com/soopgyeol/api/domain/challenge/entity/DailyChallenge.java deleted file mode 100644 index 1f14503..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/challenge/entity/DailyChallenge.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.soopgyeol.api.domain.challenge.entity; - -import com.soopgyeol.api.domain.enums.Category; -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.annotations.CreationTimestamp; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -@Entity -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class DailyChallenge { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "daily_challenge_id") - private Long id; - - private String title; - - @Column(name = "goal_count") - private int goalCount; - - @Column(name = "reward_money") - private int rewardMoney; - - @Column(name = "carbon_keyword") - private String carbonKeyword; - - @Column(name = "is_active") - private boolean isActive; - - @Column(name = "created_at", updatable = false) - @CreationTimestamp - private LocalDateTime createdAt; - - @Enumerated(EnumType.STRING) - private Category category; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/enums/Category.java b/server/src/main/java/com/soopgyeol/api/domain/enums/Category.java deleted file mode 100644 index 66ae6c7..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/enums/Category.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.soopgyeol.api.domain.enums; - -public enum Category { - FOOD("음식", "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/FOOD.jpg"), - TRANSPORT("교통", "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/TRANSPORTATION.jpg"), - CLOTHING("의류", "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/CLOTHING.jpg"), - HOUSING_ENERGY("주거 및 에너지", "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/HOUSING_ENERGY.jpg"), - RECYCLE_WASTE("리사이클 & 폐기물", "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/RECYCLE.jpg"), - LIFESTYLE_CONSUMPTION("라이프스타일 & 소비", "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/LIFESTYLE.jpg"), - ETC("기타", "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/ETC.JPG"); - - private final String description; - private final String imageUrl; - - Category(String description, String imageUrl) { - this.description = description; - this.imageUrl = imageUrl; - } - - public String getDescription() { - return description; - } - - public String getImageUrl() { - return imageUrl; - } - - public static Category fromString(String value) { - for (Category category : Category.values()) { - if (category.name().equalsIgnoreCase(value.trim())) { - return category; - } - } - return ETC; // fallback - } - -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/domain/enums/ItemCategory.java b/server/src/main/java/com/soopgyeol/api/domain/enums/ItemCategory.java deleted file mode 100644 index 11543d5..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/enums/ItemCategory.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.soopgyeol.api.domain.enums; - -public enum ItemCategory { - SKY, - LEFT_GROUND, - RIGHT_GROUND, -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/domain/item/dto/DisplayResponse.java b/server/src/main/java/com/soopgyeol/api/domain/item/dto/DisplayResponse.java deleted file mode 100644 index 0c91ae8..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/item/dto/DisplayResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soopgyeol.api.domain.item.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class DisplayResponse { - private Long itemId; - private boolean display; - private String message; -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/domain/item/dto/ItemResponse.java b/server/src/main/java/com/soopgyeol/api/domain/item/dto/ItemResponse.java deleted file mode 100644 index ee171ac..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/item/dto/ItemResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.soopgyeol.api.domain.item.dto; - -import com.soopgyeol.api.domain.enums.ItemCategory; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class ItemResponse { - private Long id; - private String name; - private int price; - private String url; - private ItemCategory category; - private boolean display; - private boolean available; - private boolean isBuyed; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/item/entity/Inventory.java b/server/src/main/java/com/soopgyeol/api/domain/item/entity/Inventory.java deleted file mode 100644 index 025694f..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/item/entity/Inventory.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.soopgyeol.api.domain.item.entity; - - -import com.soopgyeol.api.domain.user.User; -import jakarta.persistence.*; -import lombok.*; - -import java.time.LocalDateTime; - -@Entity -@Table(name = "inventory") -@Getter -@Setter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Builder -public class Inventory { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "user_item_id") - private Long userItemId; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "item_id") - private Item item; - - // 전시 여부 - @Column(name = "is_displayed") - private boolean isDisplayed; - - // 보유(구매) 여부 - @Column(name = "is_buyed") - private boolean isBuyed; - - // 구매 시간 - @Column(name = "buy_at") - private LocalDateTime buyAt; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/item/entity/Item.java b/server/src/main/java/com/soopgyeol/api/domain/item/entity/Item.java deleted file mode 100644 index c70289f..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/item/entity/Item.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.soopgyeol.api.domain.item.entity; - - -import com.soopgyeol.api.domain.enums.ItemCategory; -import jakarta.persistence.*; -import lombok.*; - -@Entity -@Table(name = "item") -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Builder -public class Item { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(nullable = false) - private String name; - - @Column(nullable = false) - private int price; - - private String url; - - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private ItemCategory category; - - public void setPrice(int price) { - this.price = price; - } -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/stage/dto/HeroStageRequest.java b/server/src/main/java/com/soopgyeol/api/domain/stage/dto/HeroStageRequest.java deleted file mode 100644 index 3adbc51..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/stage/dto/HeroStageRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.soopgyeol.api.domain.stage.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class HeroStageRequest { - private Long userId; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/stage/dto/HeroStageResponse.java b/server/src/main/java/com/soopgyeol/api/domain/stage/dto/HeroStageResponse.java deleted file mode 100644 index f98748a..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/stage/dto/HeroStageResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soopgyeol.api.domain.stage.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class HeroStageResponse { - private String heroName; - private String heroUrl; -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/domain/stage/dto/TreeStageRequest.java b/server/src/main/java/com/soopgyeol/api/domain/stage/dto/TreeStageRequest.java deleted file mode 100644 index f4b787a..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/stage/dto/TreeStageRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.soopgyeol.api.domain.stage.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class TreeStageRequest { - private Long userId; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/stage/dto/TreeStageResponse.java b/server/src/main/java/com/soopgyeol/api/domain/stage/dto/TreeStageResponse.java deleted file mode 100644 index da27b9d..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/stage/dto/TreeStageResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soopgyeol.api.domain.stage.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class TreeStageResponse { - private String treeName; - private String treeUrl; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/stage/entity/Stage.java b/server/src/main/java/com/soopgyeol/api/domain/stage/entity/Stage.java deleted file mode 100644 index 14b46ef..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/stage/entity/Stage.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.soopgyeol.api.domain.stage.entity; - - -import com.soopgyeol.api.domain.user.User; -import jakarta.persistence.*; -import lombok.*; - -@Entity -@Table(name = "stage") -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Builder -public class Stage { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - // User와 1:1 관계 - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id", unique = true) - private User user; - - // 트리 정보 - @Column(nullable = false) - private String treeName; - - private String treeUrl; - - // 히어로 정보 - @Column(nullable = false) - private String heroName; - - private String heroUrl; - - public void setUser(User user) { - this.user = user; - } - - public void setTreeName(String treeName) { - this.treeName = treeName; - } - - public void setTreeUrl(String treeUrl) { - this.treeUrl = treeUrl; - } - - public void setHeroName(String heroName) { - this.heroName = heroName; - } - - public void setHeroUrl(String heroUrl) { - this.heroUrl = heroUrl; - } -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/domain/user/Role.java b/server/src/main/java/com/soopgyeol/api/domain/user/Role.java deleted file mode 100644 index 0149ab9..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/user/Role.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soopgyeol.api.domain.user; - -import lombok.Getter; - -@Getter -public enum Role { - - USER("ROLE_USER"), - ADMIN("ROLE_ADMIN"); - private final String key; - - Role(String key) { - this.key = key; - } -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/user/SocialLoginType.java b/server/src/main/java/com/soopgyeol/api/domain/user/SocialLoginType.java deleted file mode 100644 index b1883d3..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/user/SocialLoginType.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.soopgyeol.api.domain.user; - -public enum SocialLoginType { - GOOGLE, KAKAO -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/user/User.java b/server/src/main/java/com/soopgyeol/api/domain/user/User.java deleted file mode 100644 index 2b74905..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/user/User.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.soopgyeol.api.domain.user; - -import jakarta.persistence.*; -import lombok.*; -import org.hibernate.annotations.CreationTimestamp; -import org.hibernate.annotations.UpdateTimestamp; - -import java.time.LocalDateTime; - -@Entity -@Getter -@Setter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Builder -public class User { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "user_id") - private Long id; - - @Column(nullable = false, unique = true) - private String email; - - private String password; - - private String nickname; - - @Enumerated(EnumType.STRING) - private Role role; // USER, ADMIN - - @Enumerated(EnumType.STRING) - private SocialLoginType provider; // GOOGLE, KAKAO - - private String socialId; - - @Column(name = "money_balance", nullable = false) - private int moneyBalance; - - @Column(name = "growth_point", nullable = false) - private int growthPoint; - - @CreationTimestamp - private LocalDateTime createdAt; - - @UpdateTimestamp - private LocalDateTime updatedAt; - - public void increaseGrowthPoint(int point) { - this.growthPoint += point; - } - - public void addMoney(int amount) { - this.moneyBalance += amount; - } - - public void subMoney(int money) {this.moneyBalance -= money; } -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/domain/user/dto/UserInfoResponse.java b/server/src/main/java/com/soopgyeol/api/domain/user/dto/UserInfoResponse.java deleted file mode 100644 index ad612a0..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/user/dto/UserInfoResponse.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.soopgyeol.api.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public class UserInfoResponse { - private Long userId; - private String email; - private String nickname; -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/domain/userChallenge/entity/UserChallenge.java b/server/src/main/java/com/soopgyeol/api/domain/userChallenge/entity/UserChallenge.java deleted file mode 100644 index 705a6d5..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/userChallenge/entity/UserChallenge.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.soopgyeol.api.domain.userChallenge.entity; - -import com.soopgyeol.api.domain.challenge.entity.DailyChallenge; -import com.soopgyeol.api.domain.user.User; -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDate; - -@Entity -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class UserChallenge { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "user_challenge_id") - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "daily_challenge_id") - private DailyChallenge dailyChallenge; - - @Column(name = "is_completed") - private boolean isCompleted; - - @Column(name = "progress_count") - private int progressCount; - - @Column(name = "reward_money") - private int rewardMoney; - - @Column(name = "completed_at") - private LocalDate completedAt; - - @Builder.Default - @Column(name = "reward_received", nullable = false) - private boolean rewardReceived = false; - - public void setRewardReceived(boolean rewardReceived) { - this.rewardReceived = rewardReceived; - } - - public void increaseProgress(int quantity) { - this.progressCount += quantity; - if (this.progressCount >= this.dailyChallenge.getGoalCount()) { - this.isCompleted = true; - } - } -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/dto/UserCarbonLogRequest.java b/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/dto/UserCarbonLogRequest.java deleted file mode 100644 index 2ce1251..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/dto/UserCarbonLogRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.soopgyeol.api.domain.usercarbonlog.dto; - -import lombok.Data; - -@Data -public class UserCarbonLogRequest { - private Long userId; - private Long carbonItemId; - private int quantity; - private Long dailyChallengeId; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/dto/UserCarbonLogResponse.java b/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/dto/UserCarbonLogResponse.java deleted file mode 100644 index f637c0a..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/dto/UserCarbonLogResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.soopgyeol.api.domain.usercarbonlog.dto; - -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class UserCarbonLogResponse { - private String product; - private int growthPoint; -} diff --git a/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/dto/UserCarbonLogSummaryResponse.java b/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/dto/UserCarbonLogSummaryResponse.java deleted file mode 100644 index 75d6f06..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/dto/UserCarbonLogSummaryResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.soopgyeol.api.domain.usercarbonlog.dto; - -import lombok.Builder; -import lombok.Data; - -import java.util.List; - -@Data -@Builder -public class UserCarbonLogSummaryResponse { - private List logs; - private int totalGrowthPoint; -} - diff --git a/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/entity/UserCarbonLog.java b/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/entity/UserCarbonLog.java deleted file mode 100644 index 3d77fdb..0000000 --- a/server/src/main/java/com/soopgyeol/api/domain/usercarbonlog/entity/UserCarbonLog.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.soopgyeol.api.domain.usercarbonlog.entity; - -import com.soopgyeol.api.domain.carbon.entity.CarbonItem; -import com.soopgyeol.api.domain.challenge.entity.DailyChallenge; -import com.soopgyeol.api.domain.user.User; -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -@Entity -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class UserCarbonLog { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "log_id") - private Long id; - - // 소비한 사용자 - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - // 소비한 품목 - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "carbon_item_id") - private CarbonItem carbonItem; - - // 소비 수량 - private int quantity; - - // 계산된 총 탄소량 - @Column(name = "calculated_carbon", nullable = false) - private float calculatedCarbon; - - @Column(name = "calculated_point", nullable = false) - private int growthPoint; - - // 저장 시각 - @Column(nullable = false) - private LocalDateTime recordedAt; - - @Column(nullable = false) - private boolean isFromChallenge; -} diff --git a/server/src/main/java/com/soopgyeol/api/dto/oauth/GoogleTokenResponse.java b/server/src/main/java/com/soopgyeol/api/dto/oauth/GoogleTokenResponse.java deleted file mode 100644 index de3b208..0000000 --- a/server/src/main/java/com/soopgyeol/api/dto/oauth/GoogleTokenResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soopgyeol.api.dto.oauth; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@JsonIgnoreProperties(ignoreUnknown = true) -@NoArgsConstructor -public class GoogleTokenResponse { - - @JsonProperty("access_token") - private String accessToken; - - @JsonProperty("id_token") - private String idToken; -} - diff --git a/server/src/main/java/com/soopgyeol/api/dto/oauth/KakaoTokenResponse.java b/server/src/main/java/com/soopgyeol/api/dto/oauth/KakaoTokenResponse.java deleted file mode 100644 index 7972034..0000000 --- a/server/src/main/java/com/soopgyeol/api/dto/oauth/KakaoTokenResponse.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.soopgyeol.api.dto.oauth; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class KakaoTokenResponse { - - @JsonProperty("access_token") - private String accessToken; - - @JsonProperty("token_type") - private String tokenType; - - @JsonProperty("refresh_token") - private String refreshToken; - - @JsonProperty("expires_in") - private Long expiresIn; - - @JsonProperty("scope") - private String scope; - - @JsonProperty("refresh_token_expires_in") - private Long refreshTokenExpiresIn; -} diff --git a/server/src/main/java/com/soopgyeol/api/dto/oauth/OAuthLoginRequest.java b/server/src/main/java/com/soopgyeol/api/dto/oauth/OAuthLoginRequest.java deleted file mode 100644 index 55a3489..0000000 --- a/server/src/main/java/com/soopgyeol/api/dto/oauth/OAuthLoginRequest.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soopgyeol.api.dto.oauth; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class OAuthLoginRequest { - private String provider; - private String code; -} diff --git a/server/src/main/java/com/soopgyeol/api/dto/oauth/OAuthLoginResponse.java b/server/src/main/java/com/soopgyeol/api/dto/oauth/OAuthLoginResponse.java deleted file mode 100644 index 6be8775..0000000 --- a/server/src/main/java/com/soopgyeol/api/dto/oauth/OAuthLoginResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soopgyeol.api.dto.oauth; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class OAuthLoginResponse { - private String jwtToken; - private boolean isNewUser; -} diff --git a/server/src/main/java/com/soopgyeol/api/dto/oauth/SocialUserInfo.java b/server/src/main/java/com/soopgyeol/api/dto/oauth/SocialUserInfo.java deleted file mode 100644 index af2d786..0000000 --- a/server/src/main/java/com/soopgyeol/api/dto/oauth/SocialUserInfo.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soopgyeol.api.dto.oauth; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class SocialUserInfo { - private String socialId; - private String email; - private String nickname; - -} diff --git a/server/src/main/java/com/soopgyeol/api/repository/CarbonItemRepository.java b/server/src/main/java/com/soopgyeol/api/repository/CarbonItemRepository.java deleted file mode 100644 index 8462710..0000000 --- a/server/src/main/java/com/soopgyeol/api/repository/CarbonItemRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.soopgyeol.api.repository; - -import com.soopgyeol.api.domain.carbon.entity.CarbonItem; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface CarbonItemRepository extends JpaRepository { -} diff --git a/server/src/main/java/com/soopgyeol/api/repository/DailyChallengeRepository.java b/server/src/main/java/com/soopgyeol/api/repository/DailyChallengeRepository.java deleted file mode 100644 index cbf78b9..0000000 --- a/server/src/main/java/com/soopgyeol/api/repository/DailyChallengeRepository.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soopgyeol.api.repository; - -import com.soopgyeol.api.domain.challenge.entity.DailyChallenge; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; - -import java.util.Optional; - -public interface DailyChallengeRepository extends JpaRepository { - Optional findByIsActiveTrue(); - - @Modifying - @Query("UPDATE DailyChallenge dc SET dc.isActive = false WHERE dc.isActive = true") - void deactivateAll(); -} diff --git a/server/src/main/java/com/soopgyeol/api/repository/InventoryRepository.java b/server/src/main/java/com/soopgyeol/api/repository/InventoryRepository.java deleted file mode 100644 index 8064dd0..0000000 --- a/server/src/main/java/com/soopgyeol/api/repository/InventoryRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.soopgyeol.api.repository; - -import com.soopgyeol.api.domain.item.entity.Inventory; -import com.soopgyeol.api.domain.item.entity.Item; -import com.soopgyeol.api.domain.user.User; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.List; - -public interface InventoryRepository extends JpaRepository { - List findByUser(User user); - - List findByUserAndIsDisplayedTrue(User user); - - List findByUserAndIsBuyedTrue(User user); - - List findByUserAndItem(User user, Item item); - - void deleteByUser(User user); -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/repository/ItemRepository.java b/server/src/main/java/com/soopgyeol/api/repository/ItemRepository.java deleted file mode 100644 index 93966a3..0000000 --- a/server/src/main/java/com/soopgyeol/api/repository/ItemRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.soopgyeol.api.repository; - -import com.soopgyeol.api.domain.item.entity.Item; -import com.soopgyeol.api.domain.enums.ItemCategory; -import org.springframework.data.jpa.repository.JpaRepository; -import java.util.List; - -public interface ItemRepository extends JpaRepository { - List findByCategory(ItemCategory category); -} diff --git a/server/src/main/java/com/soopgyeol/api/repository/PurchaseRepository.java b/server/src/main/java/com/soopgyeol/api/repository/PurchaseRepository.java deleted file mode 100644 index 2a85f51..0000000 --- a/server/src/main/java/com/soopgyeol/api/repository/PurchaseRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soopgyeol.api.repository; - -import com.soopgyeol.api.domain.item.entity.Item; -import com.soopgyeol.api.domain.user.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; -import com.soopgyeol.api.domain.buy.entity.Purchase; - -@Repository -public interface PurchaseRepository extends JpaRepository { - - boolean existsByUserAndItem(User user, Item item); -} diff --git a/server/src/main/java/com/soopgyeol/api/repository/StageRepository.java b/server/src/main/java/com/soopgyeol/api/repository/StageRepository.java deleted file mode 100644 index 283a96b..0000000 --- a/server/src/main/java/com/soopgyeol/api/repository/StageRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soopgyeol.api.repository; - -import com.soopgyeol.api.domain.stage.entity.Stage; -import com.soopgyeol.api.domain.user.User; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface StageRepository extends JpaRepository { - Optional findByUser(User user); - - void deleteByUser(User user); -} diff --git a/server/src/main/java/com/soopgyeol/api/repository/UserCarbonLogRepository.java b/server/src/main/java/com/soopgyeol/api/repository/UserCarbonLogRepository.java deleted file mode 100644 index c5dc5f1..0000000 --- a/server/src/main/java/com/soopgyeol/api/repository/UserCarbonLogRepository.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.soopgyeol.api.repository; - -import com.soopgyeol.api.domain.usercarbonlog.entity.UserCarbonLog; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; - -public interface UserCarbonLogRepository extends JpaRepository { - - List findByUserIdAndRecordedAtBetween(Long userId, LocalDateTime start, LocalDateTime end); - - List findByUserIdAndRecordedAtBetweenAndIsFromChallengeTrue(Long userId, LocalDateTime start, - LocalDateTime end); - - void deleteByUserId(Long userId); - -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/repository/UserChallengeRepository.java b/server/src/main/java/com/soopgyeol/api/repository/UserChallengeRepository.java deleted file mode 100644 index 91c1288..0000000 --- a/server/src/main/java/com/soopgyeol/api/repository/UserChallengeRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soopgyeol.api.repository; - -import com.soopgyeol.api.domain.challenge.entity.DailyChallenge; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.domain.userChallenge.entity.UserChallenge; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.List; -import java.util.Optional; - -public interface UserChallengeRepository extends JpaRepository { - Optional findByUserAndDailyChallenge(User user, DailyChallenge dailyChallenge); - - List findAllByUserIdOrderByDailyChallengeCreatedAtDesc(Long userId); - - void deleteByUser(User user); -} diff --git a/server/src/main/java/com/soopgyeol/api/repository/UserRepository.java b/server/src/main/java/com/soopgyeol/api/repository/UserRepository.java deleted file mode 100644 index d240ee3..0000000 --- a/server/src/main/java/com/soopgyeol/api/repository/UserRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soopgyeol.api.repository; - - -import com.soopgyeol.api.domain.user.SocialLoginType; -import com.soopgyeol.api.domain.user.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -@Repository -public interface UserRepository extends JpaRepository { - - Optional findBySocialIdAndProvider(String socialId, SocialLoginType provider); - - Optional findByEmail(String email); -} diff --git a/server/src/main/java/com/soopgyeol/api/service/UserService.java b/server/src/main/java/com/soopgyeol/api/service/UserService.java deleted file mode 100644 index 5e0e5da..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/UserService.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.soopgyeol.api.service; - -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.repository.UserRepository; -import com.soopgyeol.api.repository.StageRepository; -import com.soopgyeol.api.repository.InventoryRepository; -import com.soopgyeol.api.repository.UserChallengeRepository; -import com.soopgyeol.api.repository.UserCarbonLogRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional -public class UserService { - - private final UserRepository userRepository; - private final StageRepository stageRepository; - private final InventoryRepository inventoryRepository; - private final UserChallengeRepository userChallengeRepository; - private final UserCarbonLogRepository userCarbonLogRepository; - - public String updateNickname(Long userId, String nickname) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("유저를 찾을 수 없습니다.")); - - user.setNickname(nickname); - userRepository.save(user); - return nickname; - } - - @Transactional(readOnly = true) - public User getUserById(Long userId) { - return userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("User not found")); - } - - public void deleteUser(Long userId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("유저를 찾을 수 없습니다.")); - stageRepository.deleteByUser(user); - inventoryRepository.deleteByUser(user); - userChallengeRepository.deleteByUser(user); - userCarbonLogRepository.deleteByUserId(userId); - userRepository.delete(user); - } - -} diff --git a/server/src/main/java/com/soopgyeol/api/service/auth/GoogleOauth.java b/server/src/main/java/com/soopgyeol/api/service/auth/GoogleOauth.java deleted file mode 100644 index 6b8610d..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/auth/GoogleOauth.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.soopgyeol.api.service.auth; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.soopgyeol.api.domain.user.SocialLoginType; -import com.soopgyeol.api.dto.oauth.SocialUserInfo; -import io.github.cdimascio.dotenv.Dotenv; -import lombok.AllArgsConstructor; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.util.UriComponentsBuilder; - -import java.io.IOException; - - -@Component -@AllArgsConstructor -public class GoogleOauth implements SocialOauth { - - private final RestTemplate rest = new RestTemplate(); - private final ObjectMapper om = new ObjectMapper(); - - private final String clientId; - private final String clientSecret; - - @Value("${oauth.google.redirect-uri}") - private String redirectUri; - - - @Autowired - public GoogleOauth(Dotenv dotenv) { - this.clientId = dotenv.get("GOOGLE_CLIENT_ID"); - this.clientSecret = dotenv.get("GOOGLE_CLIENT_SECRET"); - //this.redirectUri = dotenv.get("GOOGLE_REDIRECT_URI"); - - } - @Override - public SocialLoginType type() { - return SocialLoginType.GOOGLE; - } - - @Override - public String getOauthRedirectURL() { - return UriComponentsBuilder - .fromUriString("https://accounts.google.com/o/oauth2/v2/auth") - .queryParam("client_id", clientId) - .queryParam("redirect_uri", redirectUri) - .queryParam("response_type", "code") - .queryParam("scope", "openid email profile") - .build() - .encode() - .toUriString(); - } - - @Override - public String requestAccessToken(String code) { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - - MultiValueMap params = new LinkedMultiValueMap<>(); - params.add("grant_type", "authorization_code"); - params.add("code", code); - params.add("client_id", clientId); - params.add("client_secret", clientSecret); - params.add("redirect_uri", redirectUri); - - - HttpEntity> request = new HttpEntity<>(params, headers); - - try { - String tokenJson = rest.postForObject( - "https://oauth2.googleapis.com/token", - request, - String.class - ); - return tokenJson; - } catch (HttpClientErrorException ex) { - System.out.println("❌ token 요청 실패: " + ex.getResponseBodyAsString()); - throw ex; - } - } - - - @Override - public SocialUserInfo getUserInfo(String accessToken, String ignore) throws IOException { - HttpHeaders h = new HttpHeaders(); - h.setBearerAuth(accessToken); - - String json = rest.exchange( - "https://openidconnect.googleapis.com/v1/userinfo", - HttpMethod.GET, - new HttpEntity<>(h), - String.class - ).getBody(); - - JsonNode n = om.readTree(json); - return new SocialUserInfo( - n.get("sub").asText(), - n.get("email").asText(), - n.get("name").asText() - ); - } -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/service/auth/KakaoOauth.java b/server/src/main/java/com/soopgyeol/api/service/auth/KakaoOauth.java deleted file mode 100644 index ba29022..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/auth/KakaoOauth.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.soopgyeol.api.service.auth; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.soopgyeol.api.domain.user.SocialLoginType; -import com.soopgyeol.api.dto.oauth.SocialUserInfo; -import io.github.cdimascio.dotenv.Dotenv; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.util.UriComponentsBuilder; - -import java.io.IOException; - -@Component -@RequiredArgsConstructor -public class KakaoOauth implements SocialOauth { - - private final RestTemplate rest = new RestTemplate(); - private final ObjectMapper om = new ObjectMapper(); - private final Dotenv dotenv = Dotenv.load(); - - private final String clientId = dotenv.get("KAKAO_CLIENT_ID"); - - //private final String redirectUri = dotenv.get("KAKAO_REDIRECT_URI"); - @Value("${oauth.kakao.redirect-uri}") - private String redirectUri; - private final String clientSecret = dotenv.get("KAKAO_CLIENT_SECRET"); // optional - - @Override - public SocialLoginType type() { - return SocialLoginType.KAKAO; - } - - @Override - public String getOauthRedirectURL() { - return UriComponentsBuilder.fromUriString("https://kauth.kakao.com/oauth/authorize") - .queryParam("client_id", clientId) - .queryParam("redirect_uri", redirectUri) - .queryParam("response_type", "code") - .queryParam("scope", "profile_nickname account_email") - .build() - .toUriString(); - } - - @Override - public String requestAccessToken(String code) { - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("grant_type", "authorization_code"); - body.add("client_id", clientId); - body.add("client_secret", clientSecret); - body.add("code", code); - body.add("redirect_uri", redirectUri); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - - return rest.postForObject( - "https://kauth.kakao.com/oauth/token", - new HttpEntity<>(body, headers), - String.class - ); - } - - @Override - public SocialUserInfo getUserInfo(String accessToken, String ignore) throws IOException { - HttpHeaders headers = new HttpHeaders(); - headers.setBearerAuth(accessToken); - - String json = rest.exchange( - "https://kapi.kakao.com/v2/user/me", - HttpMethod.GET, - new HttpEntity<>(headers), - String.class - ).getBody(); - - JsonNode node = om.readTree(json); - return new SocialUserInfo( - String.valueOf(node.get("id").asLong()), - node.at("/kakao_account/email").asText(), - node.at("/kakao_account/profile/nickname").asText() - ); - } -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/service/auth/OAuthService.java b/server/src/main/java/com/soopgyeol/api/service/auth/OAuthService.java deleted file mode 100644 index 081e06e..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/auth/OAuthService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.soopgyeol.api.service.auth; - -import com.soopgyeol.api.dto.oauth.OAuthLoginRequest; -import com.soopgyeol.api.dto.oauth.OAuthLoginResponse; - - -public interface OAuthService { - OAuthLoginResponse login(OAuthLoginRequest request); -} diff --git a/server/src/main/java/com/soopgyeol/api/service/auth/OAuthServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/auth/OAuthServiceImpl.java deleted file mode 100644 index e428ad4..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/auth/OAuthServiceImpl.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.soopgyeol.api.service.auth; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.soopgyeol.api.domain.user.Role; -import com.soopgyeol.api.domain.user.SocialLoginType; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.dto.oauth.*; -import com.soopgyeol.api.repository.UserRepository; -import com.soopgyeol.api.service.jwt.JwtProvider; -import jakarta.annotation.PostConstruct; -import lombok.RequiredArgsConstructor; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; - -import java.io.IOException; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.*; - -@Service -public class OAuthServiceImpl implements OAuthService { - - - private final Map oauthMap = new EnumMap<>(SocialLoginType.class); - private final UserRepository userRepository; - private final PasswordEncoder passwordEncoder; - private final JwtProvider jwtProvider; - private final ObjectMapper mapper = new ObjectMapper(); - - private final Set usedCodes = ConcurrentHashMap.newKeySet(); - private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); - - - public OAuthServiceImpl(List oauthList, - UserRepository userRepository, - PasswordEncoder passwordEncoder, - JwtProvider jwtProvider) { - - this.userRepository = userRepository; - this.passwordEncoder = passwordEncoder; - this.jwtProvider = jwtProvider; - - oauthList.forEach(o -> oauthMap.put(o.type(), o)); - } - - @PostConstruct - void logProvider() { - System.out.println(">>> 활성 SocialOauth = " + oauthMap.keySet()); // [GOOGLE, KAKAO] - } - - - @Override - public OAuthLoginResponse login(OAuthLoginRequest request) { - - - - if (!usedCodes.add(request.getCode())) { - System.out.println("### DUPLICATE CODE BLOCKED: " + request.getCode()); - throw new IllegalStateException("이미 사용한 authorization_code"); - } - - scheduler.schedule(() -> usedCodes.remove(request.getCode()), - 10, TimeUnit.MINUTES); - - - SocialLoginType type; - try { - type = SocialLoginType.valueOf(request.getProvider().toUpperCase()); - } catch (IllegalArgumentException e) { - throw new IllegalStateException("지원하지 않는 provider: " + request.getProvider()); - } - - - SocialOauth oauth = oauthMap.get(type); - if (oauth == null) - throw new IllegalStateException("provider 매핑 실패: " + type); - - - String tokenJson = oauth.requestAccessToken(request.getCode()); -// System.out.println(">>> tokenJson = " + tokenJson); - - - String accessToken; - String idToken = null; - try { - if (type == SocialLoginType.GOOGLE) { - GoogleTokenResponse res = mapper.readValue(tokenJson, GoogleTokenResponse.class); - accessToken = res.getAccessToken(); - idToken = res.getIdToken(); - } else { // kakao - KakaoTokenResponse res = mapper.readValue(tokenJson, KakaoTokenResponse.class); - accessToken = res.getAccessToken(); - } - } catch (IOException e) { - throw new IllegalStateException("토큰 JSON 파싱 실패", e); - } - - - SocialUserInfo info; - try { - info = oauth.getUserInfo(accessToken, idToken); - } catch (IOException e) { - throw new IllegalStateException("사용자 정보 조회 실패", e); - } - - - User user = userRepository - .findBySocialIdAndProvider(info.getSocialId(), type) - .orElseGet(() -> userRepository.saveAndFlush( - User.builder() - .email(info.getEmail()) - .nickname(info.getNickname()) - .provider(type) - .socialId(info.getSocialId()) - .password(passwordEncoder.encode("dummy")) - .role(Role.USER) - .build())); - - - String jwt = jwtProvider.createToken(user.getId(), user.getRole()); - - - return OAuthLoginResponse.builder() - .jwtToken(jwt) - .isNewUser(user.getCreatedAt().equals(user.getUpdatedAt())) - .build(); - } - -} diff --git a/server/src/main/java/com/soopgyeol/api/service/auth/SocialOauth.java b/server/src/main/java/com/soopgyeol/api/service/auth/SocialOauth.java deleted file mode 100644 index e04cd94..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/auth/SocialOauth.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soopgyeol.api.service.auth; - -import com.soopgyeol.api.domain.user.SocialLoginType; -import com.soopgyeol.api.dto.oauth.SocialUserInfo; - -import java.io.IOException; - -public interface SocialOauth { - SocialLoginType type(); // 구글 or 카카오 - String getOauthRedirectURL(); - String requestAccessToken(String code); - SocialUserInfo getUserInfo(String accessToken, String idToken) throws IOException;} - diff --git a/server/src/main/java/com/soopgyeol/api/service/buy/BuyService.java b/server/src/main/java/com/soopgyeol/api/service/buy/BuyService.java deleted file mode 100644 index b3a3dff..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/buy/BuyService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.soopgyeol.api.service.buy; - -import com.soopgyeol.api.domain.buy.dto.BuyResult; - -public interface BuyService { - BuyResult buyItem(Long userId, Long itemId); // 반드시 BuyResult로 변경 -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/service/buy/BuyServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/buy/BuyServiceImpl.java deleted file mode 100644 index fe72b98..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/buy/BuyServiceImpl.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.soopgyeol.api.service.buy; - -import com.soopgyeol.api.domain.buy.dto.BuyResult; -import com.soopgyeol.api.domain.buy.entity.Purchase; -import com.soopgyeol.api.domain.item.entity.Inventory; -import com.soopgyeol.api.domain.item.entity.Item; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.repository.InventoryRepository; -import com.soopgyeol.api.repository.ItemRepository; -import com.soopgyeol.api.repository.PurchaseRepository; -import com.soopgyeol.api.repository.UserRepository; -import com.soopgyeol.api.common.exception.InsufficientBalanceException; -import com.soopgyeol.api.common.exception.ItemAlreadyOwnedException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; - -@Service -public class BuyServiceImpl implements BuyService { - - private final ItemRepository itemRepository; - private final PurchaseRepository purchaseRepository; - private final UserRepository userRepository; - private final InventoryRepository inventoryRepository; - - public BuyServiceImpl(ItemRepository itemRepository, - PurchaseRepository purchaseRepository, - UserRepository userRepository, - InventoryRepository inventoryRepository) { - this.itemRepository = itemRepository; - this.purchaseRepository = purchaseRepository; - this.userRepository = userRepository; - this.inventoryRepository = inventoryRepository; - } - - @Transactional - @Override - public BuyResult buyItem(Long userId, Long itemId) { - - // 1. 구매 가능 여부 (사용자 금액과 아이템 금액 비교) - User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("해당 유저가 존재하지 않습니다.")); - - Item item = itemRepository.findById(itemId) - .orElseThrow(() -> new IllegalArgumentException("아이템이 존재하지 않습니다.")); - - if (user.getMoneyBalance() < item.getPrice()) { - throw new InsufficientBalanceException("보유 금액이 부족합니다."); - } - - // 2. 보유 중복 여부 - boolean alreadyOwned = purchaseRepository.existsByUserAndItem(user, item); - if (alreadyOwned) { - throw new ItemAlreadyOwnedException("이미 보유한 아이템입니다."); - } - - // 3. 금액 차감 - int money = item.getPrice(); - user.subMoney(money); - - // 4. 인벤토리 저장 - Purchase purchase = Purchase.builder() - .user(user) - .item(item) - .itemMoney(item.getPrice()) - .build(); - - purchaseRepository.save(purchase); - - Inventory inventory = Inventory.builder() - .user(user) - .item(item) - .isBuyed(true) - .isDisplayed(false) // 기본값, 필요에 따라 true로 - .buyAt(LocalDateTime.now()) - .build(); - inventoryRepository.save(inventory); - - return BuyResult.builder() - .itemId(item.getId()) - .itemName(item.getName()) - .itemPrice(item.getPrice()) - .userMoneyBalance(user.getMoneyBalance()) - .build(); - } -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/service/carbon/CarbonAnalysisService.java b/server/src/main/java/com/soopgyeol/api/service/carbon/CarbonAnalysisService.java deleted file mode 100644 index 87579b7..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/carbon/CarbonAnalysisService.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.soopgyeol.api.service.carbon; - -import com.soopgyeol.api.domain.carbon.dto.CarbonAnalysisResponse; -import com.soopgyeol.api.domain.enums.Category; - -public interface CarbonAnalysisService { - CarbonAnalysisResponse analyzeAndSave(String userInput); - - CarbonAnalysisResponse analyzeByKeyword(String keyword, Category category, Long challengeId); -} diff --git a/server/src/main/java/com/soopgyeol/api/service/carbon/CarbonAnalysisServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/carbon/CarbonAnalysisServiceImpl.java deleted file mode 100644 index af48f9e..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/carbon/CarbonAnalysisServiceImpl.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.soopgyeol.api.service.carbon; - -import com.soopgyeol.api.domain.carbon.dto.CarbonAnalysisResponse; -import com.soopgyeol.api.domain.carbon.entity.CarbonItem; -import com.soopgyeol.api.domain.enums.Category; -import com.soopgyeol.api.repository.CarbonItemRepository; -import com.soopgyeol.api.service.gpt.AIChallengeSearchService; -import com.soopgyeol.api.service.gpt.OpenAiService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; - -@Service -@RequiredArgsConstructor -public class CarbonAnalysisServiceImpl implements CarbonAnalysisService { - private final OpenAiService openAiService; - private final CarbonItemRepository carbonItemRepository; - private final AIChallengeSearchService aiChallengeSearchService; - - @Override - public CarbonAnalysisResponse analyzeAndSave(String userInput) { - // GPT 분석 요청 - CarbonAnalysisResponse analysis = openAiService.analyzeCarbon(userInput); - - analysis.setCategoryKorean(analysis.getCategory().getDescription()); - - CarbonItem carbonItem = CarbonItem.builder() - .name(analysis.getName()) - .category(analysis.getCategory()) - .carbonValue((float) analysis.getCarbonGrams()) - .growthPoint(analysis.getGrowthPoint()) - .explanation(analysis.getExplanation()) - .createdAt(LocalDateTime.now()) - .build(); - - CarbonItem savedItem = carbonItemRepository.save(carbonItem); - - return CarbonAnalysisResponse.builder() - .carbonItemId(savedItem.getId()) - .name(savedItem.getName()) - .category(savedItem.getCategory()) - .categoryKorean(analysis.getCategoryKorean()) - .carbonGrams(savedItem.getCarbonValue()) - .growthPoint(savedItem.getGrowthPoint()) - .explanation(savedItem.getExplanation()) - .categoryImageUrl(savedItem.getCategory().getImageUrl()) - .build(); - } - - @Override - public CarbonAnalysisResponse analyzeByKeyword(String keyword, Category category, Long challengeId) { - // 1. GPT로 분석 요청 (챌린지에서 제공한 키워드 기반) - CarbonAnalysisResponse analysis = aiChallengeSearchService.analyzeWithFixedCategory(keyword, category); - - - analysis.setCategoryKorean(analysis.getCategory().getDescription()); - - - CarbonItem carbonItem = CarbonItem.builder() - .name(analysis.getName()) - .category(analysis.getCategory()) - .carbonValue((float) analysis.getCarbonGrams()) - .growthPoint(analysis.getGrowthPoint()) - .explanation(analysis.getExplanation()) - .createdAt(LocalDateTime.now()) - .build(); - - CarbonItem savedItem = carbonItemRepository.save(carbonItem); - - - return CarbonAnalysisResponse.builder() - .carbonItemId(savedItem.getId()) // 저장된 ID 포함 - .name(savedItem.getName()) - .category(savedItem.getCategory()) - .categoryKorean(analysis.getCategoryKorean()) - .carbonGrams(savedItem.getCarbonValue()) - .growthPoint(savedItem.getGrowthPoint()) - .explanation(savedItem.getExplanation()) - .categoryImageUrl(savedItem.getCategory().getImageUrl()) - .challengeId(challengeId) - .build(); - } -} diff --git a/server/src/main/java/com/soopgyeol/api/service/carbonlog/UserCarbonLogService.java b/server/src/main/java/com/soopgyeol/api/service/carbonlog/UserCarbonLogService.java deleted file mode 100644 index 4a79766..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/carbonlog/UserCarbonLogService.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soopgyeol.api.service.carbonlog; - -import com.soopgyeol.api.domain.usercarbonlog.dto.UserCarbonLogRequest; -import com.soopgyeol.api.domain.usercarbonlog.dto.UserCarbonLogResponse; -import com.soopgyeol.api.domain.usercarbonlog.dto.UserCarbonLogSummaryResponse; - -import java.time.LocalDate; -import java.util.List; - -public interface UserCarbonLogService { - void saveCarbonLog(UserCarbonLogRequest request); - - UserCarbonLogSummaryResponse getLogsByUserIdAndDate(Long userId, LocalDate date); - - // 챌린지 로그만 조회 - UserCarbonLogSummaryResponse getChallengeLogsByUserIdAndDate(Long userId, LocalDate date); -} diff --git a/server/src/main/java/com/soopgyeol/api/service/carbonlog/UserCarbonLogServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/carbonlog/UserCarbonLogServiceImpl.java deleted file mode 100644 index 7f951a5..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/carbonlog/UserCarbonLogServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.soopgyeol.api.service.carbonlog; - -import com.soopgyeol.api.domain.carbon.entity.CarbonItem; -import com.soopgyeol.api.domain.challenge.entity.DailyChallenge; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.domain.userChallenge.entity.UserChallenge; -import com.soopgyeol.api.domain.usercarbonlog.dto.UserCarbonLogRequest; -import com.soopgyeol.api.domain.usercarbonlog.dto.UserCarbonLogResponse; -import com.soopgyeol.api.domain.usercarbonlog.dto.UserCarbonLogSummaryResponse; -import com.soopgyeol.api.domain.usercarbonlog.entity.UserCarbonLog; -import com.soopgyeol.api.repository.*; -import com.soopgyeol.api.service.stage.TreeStageService; -import com.soopgyeol.api.service.hero.HeroStageService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.List; - - - -@Service -@RequiredArgsConstructor -public class UserCarbonLogServiceImpl implements UserCarbonLogService { - private final UserRepository userRepository; - private final CarbonItemRepository carbonItemRepository; - private final UserCarbonLogRepository carbonLogRepository; - private final TreeStageService treeStageService; - private final HeroStageService heroStageService; - private final DailyChallengeRepository dailyChallengeRepository; - private final UserChallengeRepository userChallengeRepository; - - @Override - @Transactional - public void saveCarbonLog(UserCarbonLogRequest request) { - User user = userRepository.findById(request.getUserId()) - .orElseThrow(() -> new IllegalArgumentException("유저가 존재하지 않습니다.")); - - CarbonItem carbonItem = carbonItemRepository.findById(request.getCarbonItemId()) - .orElseThrow(() -> new IllegalArgumentException("탄소 품목이 존재하지 않습니다.")); - - int quantity = request.getQuantity(); - float totalCarbon = carbonItem.getCarbonValue() * quantity; - int totalGrowthPoint = carbonItem.getGrowthPoint() * quantity; - - // User 엔티티의 growthPoint 갱신 - user.setGrowthPoint(user.getGrowthPoint() + totalGrowthPoint); - userRepository.save(user); - - // 단계 최신화 추가 - treeStageService.updateTreeStageByGrowth(user.getId()); - heroStageService.updateHeroStageByGrowth(user.getId()); - - - boolean isFromChallenge = false; - if (request.getDailyChallengeId() != null){ - isFromChallenge = true; - - // 챌린지 정보 조회 - DailyChallenge challenge = dailyChallengeRepository.findById(request.getDailyChallengeId()) - .orElseThrow(() -> new IllegalArgumentException("챌린지 정보가 존재하지 않습니다.")); - - // 유저 챌린지 조회 - UserChallenge userChallenge = userChallengeRepository.findByUserAndDailyChallenge(user, challenge) - .orElseThrow(() -> new IllegalArgumentException("해당 유저의 챌린지 참여 정보가 없습니다.")); - - // 진행도 업데이트 - userChallenge.increaseProgress(quantity); - - - userChallengeRepository.save(userChallenge); - } - - - UserCarbonLog log = UserCarbonLog.builder() - .user(user) - .carbonItem(carbonItem) - .quantity(request.getQuantity()) - .calculatedCarbon(totalCarbon) - .growthPoint(totalGrowthPoint) - .recordedAt(LocalDateTime.now()) - .isFromChallenge(isFromChallenge) - .build(); - - carbonLogRepository.save(log); - } - - public UserCarbonLogSummaryResponse getLogsByUserIdAndDate(Long userId, LocalDate date) { - // 날짜 기준으로 시작/끝 시간 - LocalDateTime startOfDay = date.atStartOfDay(); - LocalDateTime endOfDay = date.atTime(LocalTime.MAX); - - - - List logs = carbonLogRepository.findByUserIdAndRecordedAtBetween(userId, startOfDay, - endOfDay); - - int totalGrowthPoint = logs.stream() - .mapToInt(UserCarbonLog::getGrowthPoint) - .sum(); - - List logDtos = logs.stream() - .map(log -> UserCarbonLogResponse.builder() - .product(log.getCarbonItem().getName()) - .growthPoint(log.getGrowthPoint()) - .build()) - .toList(); - - return UserCarbonLogSummaryResponse.builder() - .logs(logDtos) - .totalGrowthPoint(totalGrowthPoint) - .build(); - } - - public UserCarbonLogSummaryResponse getChallengeLogsByUserIdAndDate(Long userId, LocalDate date) { - LocalDateTime start = date.atStartOfDay(); - LocalDateTime end = date.atTime(LocalTime.MAX); - - List logs = carbonLogRepository.findByUserIdAndRecordedAtBetweenAndIsFromChallengeTrue( - userId, start, end - ); - - int totalGrowthPoint = logs.stream() - .mapToInt(UserCarbonLog::getGrowthPoint) - .sum(); - - List logDtos = logs.stream() - .map(log -> UserCarbonLogResponse.builder() - .product(log.getCarbonItem().getName()) - .growthPoint(log.getGrowthPoint()) - .build()) - .toList(); - - return UserCarbonLogSummaryResponse.builder() - .logs(logDtos) - .totalGrowthPoint(totalGrowthPoint) - .build(); - } - - -} diff --git a/server/src/main/java/com/soopgyeol/api/service/dailychallenge/UserChallengeService.java b/server/src/main/java/com/soopgyeol/api/service/dailychallenge/UserChallengeService.java deleted file mode 100644 index 0cb7d70..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/dailychallenge/UserChallengeService.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.soopgyeol.api.service.dailychallenge; - -import com.soopgyeol.api.domain.challenge.dto.ChallengeCompleteResponse; -import com.soopgyeol.api.domain.challenge.dto.ChallengeTodayResponse; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface UserChallengeService { - ChallengeTodayResponse getTodayChallengeForUser(Long userId); - ChallengeCompleteResponse completeChallenge(Long userId, Long dailyChallengeId); -} diff --git a/server/src/main/java/com/soopgyeol/api/service/dailychallenge/UserChallengeServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/dailychallenge/UserChallengeServiceImpl.java deleted file mode 100644 index df996be..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/dailychallenge/UserChallengeServiceImpl.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.soopgyeol.api.service.dailychallenge; - -import com.soopgyeol.api.domain.challenge.dto.AIChallengePromptResult; -import com.soopgyeol.api.domain.challenge.dto.ChallengeCompleteResponse; -import com.soopgyeol.api.domain.challenge.dto.ChallengeTodayResponse; -import com.soopgyeol.api.domain.challenge.dto.UserChallengeHistoryDto; -import com.soopgyeol.api.domain.challenge.entity.DailyChallenge; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.domain.userChallenge.entity.UserChallenge; -import com.soopgyeol.api.repository.DailyChallengeRepository; -import com.soopgyeol.api.repository.UserChallengeRepository; -import com.soopgyeol.api.repository.UserRepository; -import com.soopgyeol.api.service.gpt.AIChallengePromptService; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -@RequiredArgsConstructor -public class UserChallengeServiceImpl implements UserChallengeService { - - private final DailyChallengeRepository dailyChallengeRepository; - private final UserChallengeRepository userChallengeRepository; - private final AIChallengePromptService aiChallengePromptService; - private final UserRepository userRepository; - - @Override - @Transactional - public ChallengeTodayResponse getTodayChallengeForUser(Long userId) { - // 사용자 조회 - User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("해당 유저가 존재하지 않습니다.")); - - // 오늘의 챌린지 조회 or GPT로 생성 - DailyChallenge dailyChallenge = dailyChallengeRepository.findByIsActiveTrue() - .orElseGet(() -> { - // 이전 챌린지 비활성화 - dailyChallengeRepository.deactivateAll(); - - // GPT로 새로운 챌린지 생성 - AIChallengePromptResult gptResponse = aiChallengePromptService.generateChallenge(); - DailyChallenge newChallenge = DailyChallenge.builder() - .title(gptResponse.getTitle()) - .goalCount(gptResponse.getGoalCount()) - .rewardMoney(gptResponse.getRewardMoney()) - .carbonKeyword(gptResponse.getCarbonKeyword()) - .category(gptResponse.getCategory()) - .isActive(true) - .build(); - return dailyChallengeRepository.save(newChallenge); - }); - - // 유저 챌린지 참여 기록 조회 or 생성 - UserChallenge userChallenge = userChallengeRepository.findByUserAndDailyChallenge(user, dailyChallenge) - .orElseGet(() -> { - UserChallenge newChallenge = UserChallenge.builder() - .user(user) - .dailyChallenge(dailyChallenge) - .progressCount(0) - .isCompleted(false) - .build(); - return userChallengeRepository.save(newChallenge); - }); - - // DTO로 반환 - return ChallengeTodayResponse.builder() - .challengeId(dailyChallenge.getId()) - .title(dailyChallenge.getTitle()) - .goalCount(dailyChallenge.getGoalCount()) - .rewardMoney(dailyChallenge.getRewardMoney()) - .carbonKeyword(dailyChallenge.getCarbonKeyword()) - .category(dailyChallenge.getCategory()) - .progressCount(userChallenge.getProgressCount()) - .isCompleted(userChallenge.isCompleted()) - .categoryImageUrl(dailyChallenge.getCategory().getImageUrl()) - .build(); - } - - @Override - @Transactional - public ChallengeCompleteResponse completeChallenge(Long userId, Long dailyChallengeId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("유저가 존재하지 않습니다.")); - - DailyChallenge dailyChallenge = dailyChallengeRepository.findById(dailyChallengeId) - .orElseThrow(() -> new IllegalArgumentException("챌린지가 존재하지 않습니다.")); - - UserChallenge userChallenge = userChallengeRepository.findByUserAndDailyChallenge(user, dailyChallenge) - .orElseThrow(() -> new IllegalArgumentException("해당 유저의 챌린지 기록이 없습니다.")); - - if (!userChallenge.isCompleted()) { - throw new IllegalArgumentException("아직 챌린지를 완료하지 않았습니다."); - } - - if (userChallenge.isRewardReceived()) { - throw new IllegalArgumentException("이미 보상을 받은 챌린지입니다."); - } - - int reward = dailyChallenge.getRewardMoney(); - user.addMoney(reward); - userChallenge.setRewardReceived(true); - - return new ChallengeCompleteResponse(reward, user.getMoneyBalance()); - } - - @Transactional - public List getUserChallengeHistory(Long userId) { - List userChallenges = userChallengeRepository.findAllByUserIdOrderByDailyChallengeCreatedAtDesc(userId); - - return userChallenges.stream() - .map(uc -> UserChallengeHistoryDto.builder() - .title(uc.getDailyChallenge().getTitle()) - .createdAt(uc.getDailyChallenge().getCreatedAt().toLocalDate()) // 여기 변환 - .isCompleted(uc.isCompleted()) - .build()) - .toList(); - - } - -} diff --git a/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengePromptService.java b/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengePromptService.java deleted file mode 100644 index 81da166..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengePromptService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.soopgyeol.api.service.gpt; - -import com.soopgyeol.api.domain.challenge.dto.AIChallengePromptResult; - -public interface AIChallengePromptService { - AIChallengePromptResult generateChallenge(); -} diff --git a/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengePromptServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengePromptServiceImpl.java deleted file mode 100644 index 4dc41b7..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengePromptServiceImpl.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.soopgyeol.api.service.gpt; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.soopgyeol.api.domain.challenge.dto.AIChallengePromptResult; -import com.soopgyeol.api.domain.enums.Category; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import java.util.List; - -@Service -@RequiredArgsConstructor -public class AIChallengePromptServiceImpl implements AIChallengePromptService { - - private final RestTemplate restTemplate = new RestTemplate(); - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Value("${OPENAI_API_KEY}") - private String apiKey; - - private static final String OPENAI_API_URL = "https://api.openai.com/v1/chat/completions"; - - @Override - public AIChallengePromptResult generateChallenge() { - String systemPrompt = """ - 너는 탄소 절감 챌린지를 추천해주는 시스템이야. - 오늘 사용자에게 줄 수 있는 탄소 절감 챌린지를 1개 추천해줘. - - - 응답은 JSON 형식으로만 해 - - challengeTitle은 15자 이내의 짧고 명확한 챌린지 제목 - - rewardMoney는 너가 판단하기에 챌린지 난이도에 따라 5 ~ 20으로 줘! - - carbonKeyword는 기존 탄소 소비 분석 기능에서 사용하는 실생활 소비 키워드여야 해 (예: 다회용컵, 채식, 대중교통, 전기차, 에너지 절약, 음식물 쓰레기 줄이기 등) - - category는 FOOD, TRANSPORTATION, CLOTHING, HOUSING_ENERGY, RECYCLE_WASTE, LIFESTYLE_CONSUMPTION, ETC 중 하나 - { - "challengeTitle": (챌린지명), - "goalCount": (목표횟수), - "rewardMoney": (보상 돈), - "carbonKeyword": (소비 키워드), - "category": (위 category 중 하나), - } - """; - - List messages = List.of( - buildMessage("system", systemPrompt), - buildMessage("user", "오늘의 챌린지를 생성해줘") - - ); - - String requestBody = String.format(""" - { - "model": "gpt-3.5-turbo", - "messages": %s, - "temperature": 0.3 - } - """, toJson(messages)); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setBearerAuth(apiKey); - - HttpEntity entity = new HttpEntity<>(requestBody, headers); - - ResponseEntity response = restTemplate.exchange( - OPENAI_API_URL, - HttpMethod.POST, - entity, - String.class - ); - - try { - JsonNode root = objectMapper.readTree(response.getBody()); - String content = root - .path("choices").get(0) - .path("message") - .path("content") - .asText(); - - JsonNode json = objectMapper.readTree(content); - - System.out.println("GPT 응답 content: " + content); - - return AIChallengePromptResult.builder() - .title(json.get("challengeTitle").asText()) - .goalCount(json.get("goalCount").asInt()) - .rewardMoney(json.get("rewardMoney").asInt()) - .carbonKeyword(json.get("carbonKeyword").asText()) - .category(Category.fromString(json.get("category").asText())) - .build(); - } catch (Exception e){ - throw new RuntimeException("GPT 챌린지 응답 파싱 실패", e); - } - } - - private Object buildMessage(String role, String content) { - return new java.util.HashMap<>() {{ - put("role", role); - put("content", content); - }}; - } - - private String toJson(Object obj) { - try { - return objectMapper.writeValueAsString(obj); - } catch (Exception e) { - throw new RuntimeException("JSON 직렬화 실패", e); - } - } -} - diff --git a/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengeSearchService.java b/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengeSearchService.java deleted file mode 100644 index b5433e0..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengeSearchService.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soopgyeol.api.service.gpt; - -import com.soopgyeol.api.domain.carbon.dto.CarbonAnalysisResponse; -import com.soopgyeol.api.domain.enums.Category; - -public interface AIChallengeSearchService { - CarbonAnalysisResponse analyzeWithFixedCategory(String keyword, Category category); -} diff --git a/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengeSearchServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengeSearchServiceImpl.java deleted file mode 100644 index e1de5fa..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/gpt/AIChallengeSearchServiceImpl.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.soopgyeol.api.service.gpt; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.soopgyeol.api.domain.carbon.dto.CarbonAnalysisResponse; -import com.soopgyeol.api.domain.enums.Category; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import java.util.HashMap; -import java.util.List; - -@Service -@RequiredArgsConstructor -public class AIChallengeSearchServiceImpl implements AIChallengeSearchService { - private final RestTemplate restTemplate = new RestTemplate(); - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Value("${OPENAI_API_KEY}") - private String apiKey; - - private static final String OPENAI_API_URL = "https://api.openai.com/v1/chat/completions"; - - @Override - public CarbonAnalysisResponse analyzeWithFixedCategory(String keyword, Category fixedCategory) { - String systemPrompt = """ - 너는 탄소 분석 시스템이야. 사용자의 입력을 받고 다음 형식으로 JSON으로 대답해. - 품목명과, 탄소량 설명은 반드시 한글로 대답해줘. - - "growthPoint"는 사용자의 해당 활동 또는 소비에 따라서 탄소가 절감되는 정도를 너가 판단해서 0~20점 사이로 점수를 줘. - ETC는 탄소량, growthPoint 모두 0점으로 줘. - - { - "name": (품목명, 한글), - "carbonGrams": (사용자의 입력에 따라 탄소 소비량을 분석해서 반환, 숫자, g 단위), - "growthPoint": (숫자, 정수 단위), - "explanation": (왜 이 탄소량이 나왔는지 설명. 30자 이내로 간결하게 작성) - } - """; - - List messages = List.of( - buildMessage("system", systemPrompt), - buildMessage("user", keyword) - ); - - String requestBody = String.format(""" - { - "model": "gpt-3.5-turbo", - "messages": %s, - "temperature": 0.2 - } - """, toJson(messages)); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setBearerAuth(apiKey); - - HttpEntity entity = new HttpEntity<>(requestBody, headers); - - ResponseEntity response = restTemplate.exchange( - OPENAI_API_URL, - HttpMethod.POST, - entity, - String.class - ); - - try { - JsonNode root = objectMapper.readTree(response.getBody()); - String content = root.path("choices").get(0).path("message").path("content").asText(); - JsonNode json = objectMapper.readTree(content); - - return CarbonAnalysisResponse.builder() - .name(json.get("name").asText()) - .carbonGrams(json.get("carbonGrams").asDouble()) - .growthPoint(json.get("growthPoint").asInt()) - .explanation(json.get("explanation").asText()) - .category(fixedCategory) // GPT로부터 받지 않고 직접 삽입 - .build(); - - } catch (Exception e) { - throw new RuntimeException("챌린지 GPT 응답 파싱 실패", e); - } - } - - private Object buildMessage(String role, String content) { - return new HashMap<>() {{ - put("role", role); - put("content", content); - }}; - } - - private String toJson(Object obj) { - try { - return objectMapper.writeValueAsString(obj); - } catch (Exception e) { - throw new RuntimeException("JSON 직렬화 실패", e); - } - } -} diff --git a/server/src/main/java/com/soopgyeol/api/service/gpt/OpenAiService.java b/server/src/main/java/com/soopgyeol/api/service/gpt/OpenAiService.java deleted file mode 100644 index 7c45fe9..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/gpt/OpenAiService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.soopgyeol.api.service.gpt; - -import com.soopgyeol.api.domain.carbon.dto.CarbonAnalysisResponse; - -public interface OpenAiService { - CarbonAnalysisResponse analyzeCarbon(String userInput); -} diff --git a/server/src/main/java/com/soopgyeol/api/service/gpt/OpenAiServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/gpt/OpenAiServiceImpl.java deleted file mode 100644 index 1a08ad1..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/gpt/OpenAiServiceImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.soopgyeol.api.service.gpt; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.soopgyeol.api.domain.carbon.dto.CarbonAnalysisResponse; -import com.soopgyeol.api.domain.enums.Category; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import java.util.List; - -@Service -@RequiredArgsConstructor -public class OpenAiServiceImpl implements OpenAiService { - - private final RestTemplate restTemplate = new RestTemplate(); - private final ObjectMapper objectMapper = new ObjectMapper(); - - - @Value("${OPENAI_API_KEY}") - private String apiKey; - - private static final String OPENAI_API_URL = "https://api.openai.com/v1/chat/completions"; - - @Override - public CarbonAnalysisResponse analyzeCarbon(String userInput) { - String systemPrompt = """ - 너는 탄소 분석 시스템이야. 사용자의 입력을 받고 다음 형식으로 JSON으로 대답해. - 품목명과, 탄소량 설명은 반드시 한글로 대답해줘. - - - FOOD, TRANSPORTATION, CLOTHING, HOUSING_ENERGY, RECYCLE_WASTE, LIFESTYLE_CONSUMPTION, ETC 중 하나 - - "growthPoint"는 사용자의 해당 활동 또는 소비에 따라서 탄소가 절감되는 정도를 너가 판단해서 0~20점 사이로 점수를 줘. - ETC는 탄소량, growthPoint 모두 0점으로 줘. - { "name": (제품명), - "category": (위 category 중 하나), - "carbonGrams": (사용자의 입력에 따라 탄소 소비량을 분석해서 반환, 숫자, g 단위), - "growthPoint": (숫자, 정수 단위) - "explanation": (왜 이 탄소량이 나왔는지 설명. 30자 이내로 간결하게 작성) - """; - - List messages = List.of( - buildMessage("system", systemPrompt), - buildMessage("user", userInput) - ); - - // 요청 바디 구성 - String requestBody = String.format(""" - { - "model": "gpt-3.5-turbo", - "messages": %s, - "temperature": 0.2 - } - """, toJson(messages)); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setBearerAuth(apiKey); - - HttpEntity entity = new HttpEntity<>(requestBody, headers); - - // OpenAI API 호출 - ResponseEntity response = restTemplate.exchange( - OPENAI_API_URL, - HttpMethod.POST, - entity, - String.class - ); - - try { - JsonNode root = objectMapper.readTree(response.getBody()); - String content = root - .path("choices").get(0) - .path("message") - .path("content") - .asText(); - - JsonNode json = objectMapper.readTree(content); - - String name = json.get("name").asText(); - double carbonGrams = json.get("carbonGrams").asDouble(); - int growthPoint = json.get("growthPoint").asInt(); - String categoryStr = json.get("category").asText(); - String explanation = json.get("explanation").asText(); - - return CarbonAnalysisResponse.builder() - .name(name) - .category(Category.fromString(categoryStr)) - .carbonGrams(carbonGrams) - .growthPoint(growthPoint) - .explanation(explanation) - .build(); - - } catch (Exception e) { - throw new RuntimeException("GPT 응답 파싱 실패", e); - } - } - - private Object buildMessage(String role, String content) { - return new java.util.HashMap<>() {{ - put("role", role); - put("content", content); - }}; - } - - private String toJson(Object obj) { - try { - return objectMapper.writeValueAsString(obj); - } catch (Exception e) { - throw new RuntimeException("JSON 직렬화 실패", e); - } - } -} diff --git a/server/src/main/java/com/soopgyeol/api/service/hero/HeroStageService.java b/server/src/main/java/com/soopgyeol/api/service/hero/HeroStageService.java deleted file mode 100644 index 8f702b3..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/hero/HeroStageService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.soopgyeol.api.service.hero; - -import com.soopgyeol.api.domain.stage.dto.HeroStageResponse; - -public interface HeroStageService { - void updateHeroStageByGrowth(Long userId); - - HeroStageResponse getHeroStageMessage(Long userId); -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/service/hero/HeroStageServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/hero/HeroStageServiceImpl.java deleted file mode 100644 index 34650f3..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/hero/HeroStageServiceImpl.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.soopgyeol.api.service.hero; - -import com.soopgyeol.api.domain.stage.dto.HeroStageResponse; -import com.soopgyeol.api.domain.stage.entity.Stage; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.repository.StageRepository; -import com.soopgyeol.api.repository.UserRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class HeroStageServiceImpl implements HeroStageService { - private final UserRepository userRepository; - private final StageRepository stageRepository; - - @Override - @Transactional - public void updateHeroStageByGrowth(Long userId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); - Stage userStage = stageRepository.findByUser(user) - .orElseGet(() -> stageRepository.save(Stage.builder() - .user(user) - .treeName("씨앗") - .treeUrl("https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/seed.png") - .heroName("Lv.1 새싹지기") - .heroUrl("https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/hero/heroseed.png") - .build())); - - int growth = user.getGrowthPoint(); - String heroName; - String heroUrl; - if (growth <= 100) { - heroName = "Lv.1 새싹지기"; - heroUrl = "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/hero/heroseed.png"; - } else if (growth <= 300) { - heroName = "Lv.2 줄임꾼"; - heroUrl = "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/hero/herosappling.png"; - } else if (growth <= 700) { - heroName = "Lv.3 탐험가"; - heroUrl = "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/hero/herolittletree.png"; - } else { - heroName = "Lv.4 지구지킴이"; - heroUrl = "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/hero/herotree.png"; - } - - userStage.setHeroName(heroName); - userStage.setHeroUrl(heroUrl); - stageRepository.save(userStage); - } - - @Override - @Transactional - public HeroStageResponse getHeroStageMessage(Long userId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); - Stage userStage = stageRepository.findByUser(user) - .orElseGet(() -> stageRepository.save(Stage.builder() - .user(user) - .treeName("씨앗") - .treeUrl("https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/seed.png") - .heroName("Lv.1 새싹지기") - .heroUrl("https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/hero/heroseed.png") - .build())); - - String heroName = userStage.getHeroName(); - String heroUrl = userStage.getHeroUrl(); - if (heroName == null) { - throw new IllegalArgumentException("사용자의 영웅 단계 정보가 없습니다"); - } - - return HeroStageResponse.builder() - .heroName(heroName) - .heroUrl(heroUrl) - .build(); - } -} diff --git a/server/src/main/java/com/soopgyeol/api/service/item/ItemService.java b/server/src/main/java/com/soopgyeol/api/service/item/ItemService.java deleted file mode 100644 index 93cc2e4..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/item/ItemService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.soopgyeol.api.service.item; - -import com.soopgyeol.api.domain.enums.ItemCategory; -import com.soopgyeol.api.domain.item.dto.ItemResponse; -import com.soopgyeol.api.domain.item.dto.DisplayResponse; -import java.util.List; - -public interface ItemService { - List getItemsByUserIdAndCategory(Long userId, ItemCategory category); - - List getDisplayedItemsByUserId(Long userId); - - List getBuyedItemsByUserId(Long userId); - - List getBuyedItemsByUserIdAndCategory(Long userId, ItemCategory category); - - DisplayResponse toggleDisplay(Long userId, Long itemId); -} \ No newline at end of file diff --git a/server/src/main/java/com/soopgyeol/api/service/item/ItemServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/item/ItemServiceImpl.java deleted file mode 100644 index d0deb0f..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/item/ItemServiceImpl.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.soopgyeol.api.service.item; - -import com.soopgyeol.api.domain.enums.ItemCategory; -import com.soopgyeol.api.domain.item.dto.ItemResponse; -import com.soopgyeol.api.domain.item.dto.DisplayResponse; -import com.soopgyeol.api.domain.item.entity.Inventory; -import com.soopgyeol.api.domain.item.entity.Item; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.repository.InventoryRepository; -import com.soopgyeol.api.repository.ItemRepository; -import com.soopgyeol.api.repository.UserRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class ItemServiceImpl implements ItemService { - private final UserRepository userRepository; - private final InventoryRepository inventoryRepository; - private final ItemRepository itemRepository; - - @Override - public List getItemsByUserIdAndCategory(Long userId, ItemCategory category) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); - List items = itemRepository.findByCategory(category); - List inventories = inventoryRepository.findByUser(user); - return items.stream().map(item -> { - Inventory inventory = inventories.stream() - .filter(inv -> inv.getItem().getId().equals(item.getId())) - .findFirst() - .orElse(null); - boolean bought = inventory != null && inventory.isBuyed(); - boolean displayed = inventory != null && inventory.isDisplayed(); - boolean available = user.getMoneyBalance() >= item.getPrice(); - return ItemResponse.builder() - .id(item.getId()) - .name(item.getName()) - .price(item.getPrice()) - .url(item.getUrl()) - .category(item.getCategory()) - .display(displayed) - .available(available) - .isBuyed(bought) - .build(); - }).collect(Collectors.toList()); - } - - @Override - public List getDisplayedItemsByUserId(Long userId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); - return inventoryRepository.findByUserAndIsDisplayedTrue(user).stream() - .map(inventory -> toDto(inventory, user.getMoneyBalance())) - .collect(Collectors.toList()); - } - - @Override - public List getBuyedItemsByUserId(Long userId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); - return inventoryRepository.findByUserAndIsBuyedTrue(user).stream() - .map(inventory -> { - Item item = inventory.getItem(); - boolean displayed = inventory.isDisplayed(); - boolean available = user.getMoneyBalance() >= item.getPrice(); - return ItemResponse.builder() - .id(item.getId()) - .name(item.getName()) - .price(item.getPrice()) - .url(item.getUrl()) - .category(item.getCategory()) - .display(displayed) - .available(available) - .isBuyed(true) - .build(); - }) - .collect(Collectors.toList()); - } - - @Override - public List getBuyedItemsByUserIdAndCategory(Long userId, ItemCategory category) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); - return inventoryRepository.findByUserAndIsBuyedTrue(user).stream() - .filter(inventory -> inventory.getItem().getCategory() == category) - .map(inventory -> { - Item item = inventory.getItem(); - boolean displayed = inventory.isDisplayed(); - boolean available = user.getMoneyBalance() >= item.getPrice(); - return ItemResponse.builder() - .id(item.getId()) - .name(item.getName()) - .price(item.getPrice()) - .url(item.getUrl()) - .category(item.getCategory()) - .display(displayed) - .available(available) - .isBuyed(true) - .build(); - }) - .collect(Collectors.toList()); - } - - @Override - public DisplayResponse toggleDisplay(Long userId, Long itemId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); - Item item = itemRepository.findById(itemId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 아이템입니다.")); - Inventory inventory = inventoryRepository.findByUserAndItem(user, item).stream() - .filter(Inventory::isBuyed) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("해당 아이템을 보유하고 있지 않습니다.")); - boolean newDisplay = !inventory.isDisplayed(); - - if (!inventory.isDisplayed() && newDisplay) { - List displayedInventories = inventoryRepository.findByUserAndIsDisplayedTrue(user); - boolean sameCategoryDisplayed = displayedInventories.stream() - .anyMatch( - inv -> inv.getItem().getCategory() == item.getCategory() && !inv.getItem().getId().equals(item.getId())); - if (sameCategoryDisplayed) { - throw new IllegalStateException("같은 카테고리 내 다른 아이템이 이미 전시중입니다!"); - } - } - - inventory.setDisplayed(newDisplay); - inventoryRepository.save(inventory); - return DisplayResponse.builder() - .itemId(itemId) - .display(newDisplay) - .message("전시 상태가 " + (newDisplay ? "전시됨" : "전시 해제됨")) - .build(); - } - - private ItemResponse toDto(Inventory inventory, int userMoneyBalance) { - Item item = inventory.getItem(); - boolean available = userMoneyBalance >= item.getPrice(); - return ItemResponse.builder() - .id(item.getId()) - .name(item.getName()) - .price(item.getPrice()) - .url(item.getUrl()) - .category(item.getCategory()) - .display(inventory.isDisplayed()) - .available(available) - .isBuyed(inventory.isBuyed()) - .build(); - } -} diff --git a/server/src/main/java/com/soopgyeol/api/service/jwt/JwtAuthFilter.java b/server/src/main/java/com/soopgyeol/api/service/jwt/JwtAuthFilter.java deleted file mode 100644 index c0dcc80..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/jwt/JwtAuthFilter.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.soopgyeol.api.service.jwt; - -import com.soopgyeol.api.config.auth.CustomUserDetails; -import com.soopgyeol.api.domain.user.Role; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.repository.UserRepository; -import com.soopgyeol.api.service.jwt.JwtProvider; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.JwtException; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpHeaders; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; - -import java.io.IOException; -import java.util.List; - -@Slf4j -@Component -@RequiredArgsConstructor -public class JwtAuthFilter extends OncePerRequestFilter { - - private final JwtProvider jwtProvider; - private final UserRepository userRepository; - - @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, - FilterChain chain) - throws ServletException, IOException { - - String path = request.getRequestURI(); - // carbon 관련 경로만 임시 인증 우회 -// if (path.startsWith("/carbon")) { -// CustomUserDetails testUserDetails = new CustomUserDetails( -// 0L, -// "test@example.com", -// "", -// List.of(new SimpleGrantedAuthority("ROLE_USER")) -// ); -// -// UsernamePasswordAuthenticationToken authentication = -// new UsernamePasswordAuthenticationToken( -// testUserDetails, -// null, -// testUserDetails.getAuthorities() -// ); -// -// SecurityContextHolder.getContext().setAuthentication(authentication); -// chain.doFilter(request, response); -// return; -// } -// - - - String header = request.getHeader(HttpHeaders.AUTHORIZATION); - - if (header == null || !header.startsWith("Bearer ")) { - chain.doFilter(request, response); - return; - } - - String token = header.substring(7); - - try { - Claims claims = jwtProvider.parse(token); - Long userId = Long.valueOf(claims.getSubject()); - Role role = Role.valueOf((String) claims.get("role")); - - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("탈퇴한 사용자")); - - CustomUserDetails userDetails = new CustomUserDetails( - user.getId(), - user.getEmail(), - user.getPassword(), - List.of(new SimpleGrantedAuthority("ROLE_" + role.name())) - ); - - UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken( - userDetails, // Principal - null, - userDetails.getAuthorities() - ); - - SecurityContextHolder.getContext().setAuthentication(auth); - - } catch (ExpiredJwtException e) { - log.warn("JWT 만료: {}", e.getMessage()); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "토큰이 만료되었습니다."); - return; - } catch (JwtException | IllegalArgumentException e) { - log.warn("JWT 오류: {}", e.getMessage()); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "유효하지 않은 토큰입니다."); - return; - } - chain.doFilter(request, response); - } - - @Override - protected boolean shouldNotFilter(HttpServletRequest request) { - String path = request.getRequestURI(); - return path.startsWith("/api/v1/auth/oauth/") - || path.startsWith("/swagger") - || path.equals("/"); - } - -} - diff --git a/server/src/main/java/com/soopgyeol/api/service/jwt/JwtProvider.java b/server/src/main/java/com/soopgyeol/api/service/jwt/JwtProvider.java deleted file mode 100644 index 5a60e06..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/jwt/JwtProvider.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.soopgyeol.api.service.jwt; - -import com.soopgyeol.api.domain.user.Role; -import io.github.cdimascio.dotenv.Dotenv; -import io.jsonwebtoken.SignatureAlgorithm; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; - -import java.nio.charset.StandardCharsets; -import java.util.Date; - -import io.jsonwebtoken.*; -import io.jsonwebtoken.security.Keys; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import javax.crypto.SecretKey; -import java.util.Base64; -import java.util.Date; - -@Component -public class JwtProvider { - - - private final String secret; - - public JwtProvider(Dotenv dotenv) { - this.secret = dotenv.get("JWT_SECRET"); - } - - private final long ACCESS_VALIDITY = 1000L * 60 * 60 * 24 * 7; // 7일 - - - - private SecretKey getSigningKey() { - byte[] keyBytes = Base64.getDecoder().decode(secret); - return Keys.hmacShaKeyFor(keyBytes); - } - - - public String createToken(Long userId, Role role) { - long now = System.currentTimeMillis(); - - return Jwts.builder() - .setSubject(userId.toString()) - .claim("role", role.name()) - .setIssuedAt(new Date(now)) - .setExpiration(new Date(now + ACCESS_VALIDITY)) - .signWith(getSigningKey()) - .compact(); - } - - - public Claims parse(String token) throws JwtException { - return Jwts.parserBuilder() - .setSigningKey(getSigningKey()) - .build() - .parseClaimsJws(token) // 서명·만료 자동 확인 - .getBody(); // -> Claims - } - public Long getUserId(String token) { - Claims claims = Jwts.parserBuilder() - - .setSigningKey(getSigningKey()) // 수정: 일관성 유지하기 위함 - .build() - .parseClaimsJws(token) - .getBody(); - - return Long.valueOf(claims.getSubject()); - } - -} - diff --git a/server/src/main/java/com/soopgyeol/api/service/scheduler/UserGrowthScheduler.java b/server/src/main/java/com/soopgyeol/api/service/scheduler/UserGrowthScheduler.java deleted file mode 100644 index 504ff7f..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/scheduler/UserGrowthScheduler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.soopgyeol.api.service.scheduler; - -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.repository.UserRepository; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; -import java.util.List; - -@Slf4j -@Component -@RequiredArgsConstructor -public class UserGrowthScheduler { - private final UserRepository userRepository; - - // 매일 자정(00:00)에 실행 - @Scheduled(cron = "0 0 0 * * *") - public void increaseAllUsersGrowthPoint() { - List users = userRepository.findAll(); - for (User user : users) { - user.increaseGrowthPoint(10); - } - userRepository.saveAll(users); - log.info("모든 유저의 성장점수를 10점 증가시켰습니다."); - } -} diff --git a/server/src/main/java/com/soopgyeol/api/service/stage/TreeStageService.java b/server/src/main/java/com/soopgyeol/api/service/stage/TreeStageService.java deleted file mode 100644 index 4c5d34e..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/stage/TreeStageService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.soopgyeol.api.service.stage; - -import com.soopgyeol.api.domain.stage.dto.TreeStageResponse; - -public interface TreeStageService { - void updateTreeStageByGrowth(Long userId); - - TreeStageResponse getTreeStageMessage(Long userId); -} diff --git a/server/src/main/java/com/soopgyeol/api/service/stage/TreeStageServiceImpl.java b/server/src/main/java/com/soopgyeol/api/service/stage/TreeStageServiceImpl.java deleted file mode 100644 index 42f1839..0000000 --- a/server/src/main/java/com/soopgyeol/api/service/stage/TreeStageServiceImpl.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.soopgyeol.api.service.stage; - -import com.soopgyeol.api.domain.stage.dto.TreeStageResponse; -import com.soopgyeol.api.domain.stage.entity.Stage; -import com.soopgyeol.api.domain.user.User; -import com.soopgyeol.api.repository.StageRepository; -import com.soopgyeol.api.repository.UserRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class TreeStageServiceImpl implements TreeStageService { - private final UserRepository userRepository; - private final StageRepository stageRepository; - - @Override - @Transactional - public void updateTreeStageByGrowth(Long userId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); - Stage userStage = stageRepository.findByUser(user) - .orElseGet(() -> stageRepository.save(Stage.builder() - .user(user) - .treeName("씨앗") - .treeUrl("https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/seed.png") - .heroName("Lv.1 새싹지기") - .heroUrl("https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/hero/heroseed.png") - .build())); - - int growth = user.getGrowthPoint(); - String treeName; - String treeUrl; - if (growth <= 100) { - treeName = "씨앗"; - treeUrl = "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/seed.png"; - } else if (growth <= 300) { - treeName = "새싹"; - treeUrl = "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/sappling.png"; - } else if (growth <= 700) { - treeName = "작은 나무"; - treeUrl = "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/littletree.png"; - } else { - treeName = "나무"; - treeUrl = "https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/tree.png"; - } - - userStage.setTreeName(treeName); - userStage.setTreeUrl(treeUrl); - stageRepository.save(userStage); - } - - @Override - @Transactional - public TreeStageResponse getTreeStageMessage(Long userId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); - Stage userStage = stageRepository.findByUser(user) - .orElseGet(() -> stageRepository.save(Stage.builder() - .user(user) - .treeName("씨앗") - .treeUrl("https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/seed.png") - .heroName("Lv.1 새싹지기") - .heroUrl("https://soopgyeolbucket.s3.ap-northeast-2.amazonaws.com/hero/heroseed.png") - .build())); - - String treeName = userStage.getTreeName(); - String treeUrl = userStage.getTreeUrl(); - if (treeName == null) { - throw new IllegalArgumentException("사용자의 나무 단계 정보가 없습니다"); - } - - return TreeStageResponse.builder() - .treeName(treeName) - .treeUrl(treeUrl) - .build(); - } -} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index a599472..b9cc79d 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -1,48 +1,21 @@ spring: datasource: - url: ${DATABASE_URL} - username: ${DATABASE_USERNAME} - password: ${DATABASE_PASSWORD} + url: jdbc:mysql://localhost:3307/soopgyeol_db?useSSL=false&serverTimezone=Asia/Seoul&characterEncoding=UTF-8&allowPublicKeyRetrieval=true + username: root + password: newpassword123! driver-class-name: com.mysql.cj.jdbc.Driver + jpa: hibernate: - ddl-auto: update #create + ddl-auto: create show-sql: true properties: hibernate: format_sql: true + mvc: pathmatch: matching-strategy: ant_path_matcher -openai: - api: - key: ${OPENAI_API_KEY} - server: - port: 8080 - -oauth: - google: - client-id: ${GOOGLE_CLIENT_ID} - client-secret: ${GOOGLE_CLIENT_SECRET} - redirect-uri: https://soopgyeol.site/api/v1/auth/oauth/oauth2/google/code-log #${GOOGLE_REDIRECT_URI} - kakao: - client-id: ${KAKAO_CLIENT_ID} - client-secret: ${KAKAO_CLIENT_SECRET} - redirect-uri: https://soopgyeol.site/api/v1/auth/oauth/oauth2/kakao/code-log #${KAKAO_REDIRECT_URI} - -jwt: - secret: ${JWT_SECRET} - -cloud: - aws: - credentials: - access-key: ${CLOUD_AWS_CREDENTIALS_ACCESS_KEY} - secret-key: ${CLOUD_AWS_CREDENTIALS_SECRET_KEY} - s3: - bucket: ${BUCKET_NAME} - region: - static: ${CLOUD_AWS_REGION_STATIC} - stack: - auto: false + port: 3005 \ No newline at end of file