diff --git a/src/main/java/com/soptie/server/common/config/SecurityConfig.java b/src/main/java/com/soptie/server/api/config/SecurityConfig.java similarity index 94% rename from src/main/java/com/soptie/server/common/config/SecurityConfig.java rename to src/main/java/com/soptie/server/api/config/SecurityConfig.java index 20a83e74..0ab0adff 100644 --- a/src/main/java/com/soptie/server/common/config/SecurityConfig.java +++ b/src/main/java/com/soptie/server/api/config/SecurityConfig.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.config; +package com.soptie.server.api.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -11,8 +11,8 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import com.soptie.server.auth.jwt.CustomJwtAuthenticationEntryPoint; -import com.soptie.server.auth.jwt.JwtAuthenticationFilter; +import com.soptie.server.api.web.jwt.CustomJwtAuthenticationEntryPoint; +import com.soptie.server.api.web.jwt.JwtAuthenticationFilter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/soptie/server/common/config/SwaggerConfig.java b/src/main/java/com/soptie/server/api/config/SwaggerConfig.java similarity index 96% rename from src/main/java/com/soptie/server/common/config/SwaggerConfig.java rename to src/main/java/com/soptie/server/api/config/SwaggerConfig.java index cc4b2499..e8f47c38 100644 --- a/src/main/java/com/soptie/server/common/config/SwaggerConfig.java +++ b/src/main/java/com/soptie/server/api/config/SwaggerConfig.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.config; +package com.soptie.server.api.config; import static io.swagger.v3.oas.models.security.SecurityScheme.Type.*; diff --git a/src/main/java/com/soptie/server/api/controller/AuthApi.java b/src/main/java/com/soptie/server/api/controller/AuthApi.java new file mode 100644 index 00000000..c5000c27 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/AuthApi.java @@ -0,0 +1,66 @@ +package com.soptie.server.api.controller; + +import java.security.Principal; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.AuthApiDocs; +import com.soptie.server.api.controller.dto.request.auth.SignInRequest; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.auth.SignInResponse; +import com.soptie.server.api.controller.dto.response.auth.TokenGetResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.auth.AuthService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/auth") +public class AuthApi implements AuthApiDocs { + + private final AuthService authService; + + @ResponseStatus(HttpStatus.OK) + @PostMapping + public SuccessResponse signIn( + @RequestHeader("Authorization") String socialAccessToken, + @RequestBody SignInRequest request + ) { + val response = authService.signIn(socialAccessToken, request); + return SuccessResponse.success(SuccessMessage.SUCCESS_SIGN_IN.getMessage(), response); + } + + @ResponseStatus(HttpStatus.OK) + @PostMapping("/token") + public SuccessResponse reissueToken( + @RequestHeader("Authorization") String refreshToken + ) { + val response = authService.reissueToken(refreshToken); + return SuccessResponse.success(SuccessMessage.SUCCESS_RECREATE_TOKEN.getMessage(), response); + } + + @ResponseStatus(HttpStatus.OK) + @PostMapping("/logout") + public SuccessResponse signOut(Principal principal) { + val memberId = Long.parseLong(principal.getName()); + authService.signOut(memberId); + return SuccessResponse.success(SuccessMessage.SUCCESS_SIGN_OUT.getMessage()); + } + + @ResponseStatus(HttpStatus.OK) + @DeleteMapping + public SuccessResponse withdrawal(Principal principal) { + val memberId = Long.parseLong(principal.getName()); + authService.withdraw(memberId); + return SuccessResponse.success(SuccessMessage.SUCCESS_WITHDRAWAL.getMessage()); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/ChallengeApi.java b/src/main/java/com/soptie/server/api/controller/ChallengeApi.java new file mode 100644 index 00000000..827399bd --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/ChallengeApi.java @@ -0,0 +1,37 @@ +package com.soptie.server.api.controller; + +import java.security.Principal; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.ChallengeApiDocs; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.challenge.GetChallengesByMemberResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.challenge.ChallengeService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/routines/challenge") +public class ChallengeApi implements ChallengeApiDocs { + private final ChallengeService challengeService; + + @ResponseStatus(HttpStatus.OK) + @GetMapping + public SuccessResponse getChallengesByTheme( + Principal principal, + @RequestParam long themeId + ) { + val memberId = Long.parseLong(principal.getName()); + val response = challengeService.getChallengesByTheme(memberId, themeId); + return SuccessResponse.success(SuccessMessage.GET_CHALLENGE.getMessage(), response); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/MakerApi.java b/src/main/java/com/soptie/server/api/controller/MakerApi.java new file mode 100644 index 00000000..3cd8e7a9 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/MakerApi.java @@ -0,0 +1,32 @@ +package com.soptie.server.api.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.MakerApiDocs; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.maker.GetMakerListResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.maker.MakerService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/makers") +public class MakerApi implements MakerApiDocs { + + private final MakerService makerService; + + @Override + @GetMapping + @ResponseStatus(HttpStatus.OK) + public SuccessResponse acquireAll() { + val response = makerService.acquireAll(); + return SuccessResponse.success(SuccessMessage.SUCCESS_GET_MAKER_THEME.getMessage(), response); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/MemberApi.java b/src/main/java/com/soptie/server/api/controller/MemberApi.java new file mode 100644 index 00000000..bf7960e1 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/MemberApi.java @@ -0,0 +1,63 @@ +package com.soptie.server.api.controller; + +import java.security.Principal; + +import org.springframework.http.HttpStatus; +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.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.MemberApiDocs; +import com.soptie.server.api.controller.dto.request.member.CreateProfileRequest; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.member.GetHomeInfoResponse; +import com.soptie.server.api.controller.dto.response.member.GiveMemberCottonResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.member.CottonType; +import com.soptie.server.domain.member.MemberService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/members") +public class MemberApi implements MemberApiDocs { + + private final MemberService memberService; + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping + public SuccessResponse createMemberProfile( + Principal principal, + @RequestBody CreateProfileRequest request + ) { + val memberId = Long.parseLong(principal.getName()); + memberService.createMemberProfile(memberId, request); + return SuccessResponse.success(SuccessMessage.CREATE_MEMBER_PROFILE.getMessage()); + } + + @ResponseStatus(HttpStatus.OK) + @PatchMapping("/cotton/{cottonType}") + public SuccessResponse giveCotton( + Principal principal, + @PathVariable CottonType cottonType + ) { + val memberId = Long.parseLong(principal.getName()); + val response = memberService.giveCotton(memberId, cottonType); + return SuccessResponse.success(SuccessMessage.GIVE_COTTON.getMessage(), response); + } + + @ResponseStatus(HttpStatus.OK) + @GetMapping + public SuccessResponse getMemberHomeInfo(Principal principal) { + val memberId = Long.parseLong(principal.getName()); + val response = memberService.getMemberHomeInfo(memberId); + return SuccessResponse.success(SuccessMessage.GET_MEMBER_HOME.getMessage(), response); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/MemberMissionApi.java b/src/main/java/com/soptie/server/api/controller/MemberMissionApi.java new file mode 100644 index 00000000..b43d5aa7 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/MemberMissionApi.java @@ -0,0 +1,57 @@ +package com.soptie.server.api.controller; + +import java.security.Principal; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.MemberMissionApiDocs; +import com.soptie.server.api.controller.dto.request.membermission.CreateMemberMissionRequest; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.membermission.CreateMemberMissionResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.membermission.MemberMissionService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/routines/happiness/member") +public class MemberMissionApi implements MemberMissionApiDocs { + private final MemberMissionService memberMissionService; + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping + public SuccessResponse createMemberMission( + Principal principal, + @RequestBody CreateMemberMissionRequest request + ) { + val memberId = Long.parseLong(principal.getName()); + val response = memberMissionService.createMemberMission(memberId, request); + return SuccessResponse.success(SuccessMessage.CREATE_ROUTINE.getMessage(), response); + } + + @ResponseStatus(HttpStatus.OK) + @DeleteMapping("/routine/{routineId}") + public SuccessResponse deleteMemberMission(Principal principal, @PathVariable long routineId) { + val memberId = Long.parseLong(principal.getName()); + memberMissionService.deleteMemberMission(memberId, routineId); + return SuccessResponse.success(SuccessMessage.DELETE_ROUTINE.getMessage()); + } + + @ResponseStatus(HttpStatus.OK) + @PatchMapping("/routine/{routineId}") + public SuccessResponse achieveMemberMission(Principal principal, @PathVariable long routineId) { + val memberId = Long.parseLong(principal.getName()); + memberMissionService.achieveMemberMission(memberId, routineId); + return SuccessResponse.success(SuccessMessage.ACHIEVE_ROUTINE.getMessage()); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/MemberMissionApiV2.java b/src/main/java/com/soptie/server/api/controller/MemberMissionApiV2.java new file mode 100644 index 00000000..a5094be3 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/MemberMissionApiV2.java @@ -0,0 +1,32 @@ +package com.soptie.server.api.controller; + +import java.security.Principal; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.MemberMissionApiV2Docs; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.membermission.MemberMissionService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/routines/challenge/member") +public class MemberMissionApiV2 implements MemberMissionApiV2Docs { + private final MemberMissionService memberMissionService; + + @GetMapping + public ResponseEntity getMemberMission(Principal principal) { + val memberId = Long.parseLong(principal.getName()); + return memberMissionService.getMemberMission(memberId) + .map(response -> + ResponseEntity.ok(SuccessResponse.success(SuccessMessage.GET_ROUTINE.getMessage(), response))) + .orElseGet(() -> ResponseEntity.noContent().build()); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/MemberRoutineApi.java b/src/main/java/com/soptie/server/api/controller/MemberRoutineApi.java new file mode 100644 index 00000000..a2f81a03 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/MemberRoutineApi.java @@ -0,0 +1,51 @@ +package com.soptie.server.api.controller; + +import java.security.Principal; +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.MemberRoutineApiDocs; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.memberroutine.AchieveMemberRoutineResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.memberroutine.MemberRoutineService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/routines/daily/member") +public class MemberRoutineApi implements MemberRoutineApiDocs { + private final MemberRoutineService memberRoutineService; + + @ResponseStatus(HttpStatus.OK) + @DeleteMapping + public SuccessResponse deleteMemberRoutines( + Principal principal, + @RequestParam List routines + ) { + val memberId = Long.parseLong(principal.getName()); + memberRoutineService.deleteMemberRoutines(memberId, routines); + return SuccessResponse.success(SuccessMessage.DELETE_ROUTINE.getMessage()); + } + + @ResponseStatus(HttpStatus.OK) + @PatchMapping("/routine/{routineId}") + public SuccessResponse achieveMemberRoutine( + Principal principal, + @PathVariable long routineId + ) { + val memberId = Long.parseLong(principal.getName()); + val response = memberRoutineService.achieveMemberRoutine(memberId, routineId); + return SuccessResponse.success(SuccessMessage.ACHIEVE_ROUTINE.getMessage(), response); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/MemberRoutineApiV2.java b/src/main/java/com/soptie/server/api/controller/MemberRoutineApiV2.java new file mode 100644 index 00000000..661a25bb --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/MemberRoutineApiV2.java @@ -0,0 +1,47 @@ +package com.soptie.server.api.controller; + +import java.security.Principal; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.MemberRoutineApiV2Docs; +import com.soptie.server.api.controller.dto.request.memberroutine.CreateMemberRoutinesRequest; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.memberroutine.CreateMemberRoutinesResponse; +import com.soptie.server.api.controller.dto.response.memberroutine.GetMemberRoutinesResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.memberroutine.MemberRoutineService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/routines/daily/member") +public class MemberRoutineApiV2 implements MemberRoutineApiV2Docs { + private final MemberRoutineService memberRoutineService; + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping + public SuccessResponse createMemberRoutines( + Principal principal, + CreateMemberRoutinesRequest request + ) { + val memberId = Long.parseLong(principal.getName()); + val response = memberRoutineService.createRoutines(memberId, request); + return SuccessResponse.success(SuccessMessage.CREATE_ROUTINE.getMessage(), response); + } + + @ResponseStatus(HttpStatus.OK) + @GetMapping + public SuccessResponse getMemberRoutines(Principal principal) { + val memberId = Long.parseLong(principal.getName()); + val response = memberRoutineService.getMemberRoutines(memberId); + return SuccessResponse.success(SuccessMessage.GET_ROUTINE.getMessage(), response); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/RoutineApi.java b/src/main/java/com/soptie/server/api/controller/RoutineApi.java new file mode 100644 index 00000000..0e26d110 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/RoutineApi.java @@ -0,0 +1,49 @@ +package com.soptie.server.api.controller; + +import java.security.Principal; +import java.util.LinkedHashSet; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.RoutineApiDocs; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.routine.GetRoutinesByMemberResponse; +import com.soptie.server.api.controller.dto.response.routine.GetRoutinesByThemeResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.routine.RoutineService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/routines/daily") +public class RoutineApi implements RoutineApiDocs { + private final RoutineService routineService; + + @ResponseStatus(HttpStatus.OK) + @GetMapping + public SuccessResponse getRoutinesByThemeIds( + @RequestParam LinkedHashSet themeIds + ) { + val response = routineService.getRoutinesByThemeIds(themeIds); + return SuccessResponse.success(SuccessMessage.GET_ROUTINE.getMessage(), response); + } + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/theme/{themeId}") + public SuccessResponse getRoutinesByThemeId( + Principal principal, + @PathVariable long themeId + ) { + val memberId = Long.parseLong(principal.getName()); + val response = routineService.getRoutinesByThemeId(memberId, themeId); + return SuccessResponse.success(SuccessMessage.GET_ROUTINE.getMessage(), response); + } +} diff --git a/src/main/java/com/soptie/server/test/TestController.java b/src/main/java/com/soptie/server/api/controller/TestApi.java similarity index 66% rename from src/main/java/com/soptie/server/test/TestController.java rename to src/main/java/com/soptie/server/api/controller/TestApi.java index 06f3338d..8cd768c3 100644 --- a/src/main/java/com/soptie/server/test/TestController.java +++ b/src/main/java/com/soptie/server/api/controller/TestApi.java @@ -1,17 +1,17 @@ -package com.soptie.server.test; +package com.soptie.server.api.controller; -import static com.soptie.server.common.dto.SuccessResponse.*; +import static com.soptie.server.api.controller.dto.response.SuccessResponse.*; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.soptie.server.common.dto.BaseResponse; +import com.soptie.server.api.controller.dto.response.BaseResponse; @RestController @RequestMapping("/api/v1/test") -public class TestController { +public class TestApi { @GetMapping public ResponseEntity test() { diff --git a/src/main/java/com/soptie/server/api/controller/ThemeApi.java b/src/main/java/com/soptie/server/api/controller/ThemeApi.java new file mode 100644 index 00000000..5d6c4ed2 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/ThemeApi.java @@ -0,0 +1,31 @@ +package com.soptie.server.api.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.ThemeApiDocs; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.theme.GetThemesResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.theme.ThemeService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/themes") +public class ThemeApi implements ThemeApiDocs { + + private final ThemeService themeService; + + @ResponseStatus(HttpStatus.OK) + @GetMapping + public SuccessResponse getBasicThemes() { + val response = themeService.getBasicThemes(); + return SuccessResponse.success(SuccessMessage.GET_THEME.getMessage(), response); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/VersionApi.java b/src/main/java/com/soptie/server/api/controller/VersionApi.java new file mode 100644 index 00000000..0c67a691 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/VersionApi.java @@ -0,0 +1,30 @@ +package com.soptie.server.api.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.soptie.server.api.controller.docs.VersionApiDocs; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.version.GetAppVersionResponse; +import com.soptie.server.api.controller.generic.SuccessMessage; +import com.soptie.server.domain.version.VersionService; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/versions") +public class VersionApi implements VersionApiDocs { + private final VersionService versionService; + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/client/app") + public SuccessResponse getClientAppVersion() { + val response = versionService.getClientAppVersion(); + return SuccessResponse.success(SuccessMessage.GET_VERSION.getMessage(), response); + } +} diff --git a/src/main/java/com/soptie/server/auth/controller/docs/AuthControllerDocs.java b/src/main/java/com/soptie/server/api/controller/docs/AuthApiDocs.java similarity index 82% rename from src/main/java/com/soptie/server/auth/controller/docs/AuthControllerDocs.java rename to src/main/java/com/soptie/server/api/controller/docs/AuthApiDocs.java index d0a3dbea..20071cb9 100644 --- a/src/main/java/com/soptie/server/auth/controller/docs/AuthControllerDocs.java +++ b/src/main/java/com/soptie/server/api/controller/docs/AuthApiDocs.java @@ -1,17 +1,15 @@ -package com.soptie.server.auth.controller.docs; +package com.soptie.server.api.controller.docs; import java.security.Principal; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; -import com.soptie.server.auth.controller.dto.request.SignInRequest; -import com.soptie.server.auth.controller.dto.response.SignInResponse; -import com.soptie.server.auth.controller.dto.response.TokenGetResponse; -import com.soptie.server.common.dto.BaseResponse; -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; +import com.soptie.server.api.controller.dto.request.auth.SignInRequest; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.auth.SignInResponse; +import com.soptie.server.api.controller.dto.response.auth.TokenGetResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -21,7 +19,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; @Tag(name = "auth", description = "인증 API") -public interface AuthControllerDocs { +public interface AuthApiDocs { @Operation( summary = "소셜 로그인", @@ -37,7 +35,7 @@ public interface AuthControllerDocs { description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity> signIn( + SuccessResponse signIn( @RequestHeader("Authorization") String socialAccessToken, @RequestBody SignInRequest request ); @@ -64,7 +62,7 @@ ResponseEntity> signIn( description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity> reissueToken( + SuccessResponse reissueToken( @RequestHeader("Authorization") String refreshToken ); @@ -89,7 +87,7 @@ ResponseEntity> reissueToken( description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity signOut(@Parameter(hidden = true) Principal principal); + SuccessResponse signOut(@Parameter(hidden = true) Principal principal); @Operation( summary = "회원 탈퇴", @@ -112,5 +110,5 @@ ResponseEntity> reissueToken( description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity withdrawal(@Parameter(hidden = true) Principal principal); + SuccessResponse withdrawal(@Parameter(hidden = true) Principal principal); } diff --git a/src/main/java/com/soptie/server/routine/controller/v2/docs/ChallengeRoutineControllerV2Docs.java b/src/main/java/com/soptie/server/api/controller/docs/ChallengeApiDocs.java similarity index 70% rename from src/main/java/com/soptie/server/routine/controller/v2/docs/ChallengeRoutineControllerV2Docs.java rename to src/main/java/com/soptie/server/api/controller/docs/ChallengeApiDocs.java index 61436c6b..46be5965 100644 --- a/src/main/java/com/soptie/server/routine/controller/v2/docs/ChallengeRoutineControllerV2Docs.java +++ b/src/main/java/com/soptie/server/api/controller/docs/ChallengeApiDocs.java @@ -1,13 +1,12 @@ -package com.soptie.server.routine.controller.v2.docs; +package com.soptie.server.api.controller.docs; import java.security.Principal; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestParam; -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.routine.controller.v2.dto.response.ChallengeRoutineListAcquireResponseV2; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.challenge.GetChallengesByMemberResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -17,8 +16,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -@Tag(name = "challenge routines V2", description = "도전 루틴 API Version2") -public interface ChallengeRoutineControllerV2Docs { +@Tag(name = "ChallengeRoutine_v2", description = "도전 루틴 API version2") +public interface ChallengeApiDocs { @Operation( summary = "테마별 도전 루틴 목록 조회", @@ -34,7 +33,7 @@ public interface ChallengeRoutineControllerV2Docs { description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity> acquireAllByTheme( + SuccessResponse getChallengesByTheme( @Parameter(hidden = true) Principal principal, @Parameter( name = "themeId", diff --git a/src/main/java/com/soptie/server/maker/controller/docs/MakerControllerDocs.java b/src/main/java/com/soptie/server/api/controller/docs/MakerApiDocs.java similarity index 71% rename from src/main/java/com/soptie/server/maker/controller/docs/MakerControllerDocs.java rename to src/main/java/com/soptie/server/api/controller/docs/MakerApiDocs.java index 223b75f9..f60f810a 100644 --- a/src/main/java/com/soptie/server/maker/controller/docs/MakerControllerDocs.java +++ b/src/main/java/com/soptie/server/api/controller/docs/MakerApiDocs.java @@ -1,8 +1,8 @@ -package com.soptie.server.maker.controller.docs; +package com.soptie.server.api.controller.docs; -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.maker.controller.dto.response.MakerListAcquireResponse; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.maker.GetMakerListResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -11,7 +11,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; @Tag(name = "makers", description = "메이커 API") -public interface MakerControllerDocs { +public interface MakerApiDocs { @Operation( summary = "메이커 테마 리스트 조회", @@ -27,5 +27,5 @@ public interface MakerControllerDocs { description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - SuccessResponse acquireAll(); + SuccessResponse acquireAll(); } diff --git a/src/main/java/com/soptie/server/member/controller/docs/MemberControllerDocs.java b/src/main/java/com/soptie/server/api/controller/docs/MemberApiDocs.java similarity index 75% rename from src/main/java/com/soptie/server/member/controller/docs/MemberControllerDocs.java rename to src/main/java/com/soptie/server/api/controller/docs/MemberApiDocs.java index 18d94b33..bfa8ed51 100644 --- a/src/main/java/com/soptie/server/member/controller/docs/MemberControllerDocs.java +++ b/src/main/java/com/soptie/server/api/controller/docs/MemberApiDocs.java @@ -1,18 +1,16 @@ -package com.soptie.server.member.controller.docs; +package com.soptie.server.api.controller.docs; import java.security.Principal; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; -import com.soptie.server.common.dto.BaseResponse; -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.member.controller.dto.request.MemberProfileCreateRequest; -import com.soptie.server.member.controller.dto.response.MemberCottonCountGetResponse; -import com.soptie.server.member.controller.dto.response.MemberHomeInfoGetResponse; -import com.soptie.server.member.entity.CottonType; +import com.soptie.server.api.controller.dto.request.member.CreateProfileRequest; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.member.GetHomeInfoResponse; +import com.soptie.server.api.controller.dto.response.member.GiveMemberCottonResponse; +import com.soptie.server.domain.member.CottonType; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -23,15 +21,15 @@ import io.swagger.v3.oas.annotations.tags.Tag; @Tag(name = "members", description = "회원 API") -public interface MemberControllerDocs { +public interface MemberApiDocs { @Operation( - summary = "멤버 프로필 생성", - description = "멤버 프로필을 생성한다.", + summary = "회원 프로필 생성", + description = "회원의 프로필을 생성한다.", responses = { @ApiResponse( - responseCode = "200", - description = "성공", + responseCode = "201", + description = "CREATED success", content = @Content(schema = @Schema(implementation = SuccessResponse.class))), @ApiResponse( responseCode = "400", @@ -49,25 +47,21 @@ public interface MemberControllerDocs { responseCode = "409", description = "이미 존재하는 프로필", content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), @ApiResponse( responseCode = "500", description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity createMemberProfile( + SuccessResponse createMemberProfile( @Parameter(hidden = true) Principal principal, - @RequestBody MemberProfileCreateRequest request + @RequestBody CreateProfileRequest request ); @Operation( summary = "솜뭉치 주기", description = "솜뭉치를 준다.", responses = { - @ApiResponse(responseCode = "200", description = "성공"), + @ApiResponse(responseCode = "200", description = "OK success"), @ApiResponse( responseCode = "400", description = "솜뭉치 부족", @@ -89,7 +83,7 @@ ResponseEntity createMemberProfile( description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity> giveCotton( + SuccessResponse giveCotton( @Parameter(hidden = true) Principal principal, @Parameter( name = "cottonType", @@ -121,7 +115,7 @@ ResponseEntity> giveCotton( description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity> getMemberHomeInfo( + SuccessResponse getMemberHomeInfo( @Parameter(hidden = true) Principal principal ); } diff --git a/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiDocs.java b/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiDocs.java new file mode 100644 index 00000000..a0f58a1c --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiDocs.java @@ -0,0 +1,97 @@ +package com.soptie.server.api.controller.docs; + +import java.security.Principal; + +import org.springframework.web.bind.annotation.PathVariable; + +import com.soptie.server.api.controller.dto.request.membermission.CreateMemberMissionRequest; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.membermission.CreateMemberMissionResponse; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "MemberMissionApi", description = "회원의 도전 루틴 API") +public interface MemberMissionApiDocs { + + @Operation( + summary = "미션(도전 루틴) 추가", + description = "회원의 미션을 추가한다.", + responses = { + @ApiResponse(responseCode = "201", description = "Created success"), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + SuccessResponse createMemberMission( + @Parameter(hidden = true) Principal principal, + @RequestBody CreateMemberMissionRequest request + ); + + @Operation( + summary = "미션 삭제", + description = "회원의 미션을 삭제한다.", + responses = { + @ApiResponse( + responseCode = "200", + description = "OK success", + content = @Content(schema = @Schema(implementation = SuccessResponse.class))), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + SuccessResponse deleteMemberMission( + @Parameter(hidden = true) Principal principal, + @Parameter( + name = "routineId", + description = "삭제할 회원의 미션 id", + in = ParameterIn.PATH, + example = "1" + ) @PathVariable long routineId + ); + + @Operation( + summary = "미션 달성", + description = "회원의 미션을 달성한다.", + responses = { + @ApiResponse( + responseCode = "200", + description = "OK success", + content = @Content(schema = @Schema(implementation = SuccessResponse.class))), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + SuccessResponse achieveMemberMission( + @Parameter(hidden = true) Principal principal, + @Parameter( + name = "routineId", + description = "달성할 회원의 미션 id", + in = ParameterIn.PATH, + example = "1" + ) + @PathVariable long routineId + ); +} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v2/docs/MemberChallengeRoutineControllerV2Docs.java b/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiV2Docs.java similarity index 55% rename from src/main/java/com/soptie/server/memberroutine/controller/v2/docs/MemberChallengeRoutineControllerV2Docs.java rename to src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiV2Docs.java index 06697b3b..bdaf1970 100644 --- a/src/main/java/com/soptie/server/memberroutine/controller/v2/docs/MemberChallengeRoutineControllerV2Docs.java +++ b/src/main/java/com/soptie/server/api/controller/docs/MemberMissionApiV2Docs.java @@ -1,10 +1,10 @@ -package com.soptie.server.memberroutine.controller.v2.docs; +package com.soptie.server.api.controller.docs; import java.security.Principal; import org.springframework.http.ResponseEntity; -import com.soptie.server.common.dto.ErrorResponse; +import com.soptie.server.api.controller.dto.response.ErrorResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -13,18 +13,15 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -@Tag(name = "member challenge routines V2", description = "회원의 도전 루틴 API Version2") -public interface MemberChallengeRoutineControllerV2Docs { +@Tag(name = "MemberMissionApi_v2", description = "회원의 도전 루틴 API version2") +public interface MemberMissionApiV2Docs { @Operation( - summary = "회원의 도전 루틴 목록 조회", - description = "회원의 도전 루틴을 테마와 함께 조회한다.", + summary = "회원의 도전 루틴 조회", + description = "회원의 도전 루틴을 조회한다.", responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "200", description = "OK success"), + @ApiResponse(responseCode = "204", description = "NoContent success"), @ApiResponse( responseCode = "4xx", description = "클라이언트(요청) 오류", @@ -34,7 +31,7 @@ public interface MemberChallengeRoutineControllerV2Docs { description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity acquire( + ResponseEntity getMemberMission( @Parameter(hidden = true) Principal principal ); } diff --git a/src/main/java/com/soptie/server/routine/controller/v1/docs/DailyRoutineControllerDocs.java b/src/main/java/com/soptie/server/api/controller/docs/MemberRoutineApiDocs.java similarity index 55% rename from src/main/java/com/soptie/server/routine/controller/v1/docs/DailyRoutineControllerDocs.java rename to src/main/java/com/soptie/server/api/controller/docs/MemberRoutineApiDocs.java index 7c77a77d..3e859500 100644 --- a/src/main/java/com/soptie/server/routine/controller/v1/docs/DailyRoutineControllerDocs.java +++ b/src/main/java/com/soptie/server/api/controller/docs/MemberRoutineApiDocs.java @@ -1,15 +1,14 @@ -package com.soptie.server.routine.controller.v1.docs; +package com.soptie.server.api.controller.docs; import java.security.Principal; import java.util.List; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.routine.controller.v1.dto.response.DailyRoutineListAcquireResponse; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.memberroutine.AchieveMemberRoutineResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -19,14 +18,17 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -@Tag(name = "daily routines V1", description = "데일리 루틴 API Version1") -public interface DailyRoutineControllerDocs { +@Tag(name = "MemberRoutineApi", description = "회원의 데일리 루틴 API") +public interface MemberRoutineApiDocs { @Operation( - summary = "테마 목록별 데일리 루틴 목록 조회", - description = "테마 목록 중 하나라도 해당되는 데일리 루틴 목록을 이름 오름차순으로 조회한다.", + summary = "데일리 루틴 삭제", + description = "회원의 데일리 루틴을 삭제한다.", responses = { - @ApiResponse(responseCode = "200", description = "성공"), + @ApiResponse( + responseCode = "200", + description = "성공", + content = @Content(schema = @Schema(implementation = SuccessResponse.class))), @ApiResponse( responseCode = "4xx", description = "클라이언트(요청) 오류", @@ -36,18 +38,19 @@ public interface DailyRoutineControllerDocs { description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity> acquireAllByThemes( + SuccessResponse deleteMemberRoutines( + @Parameter(hidden = true) Principal principal, @Parameter( - name = "themes", - description = "조회할 데일리 루틴 테마 id 목록", + name = "routines", + description = "삭제할 회원의 데일리 루틴 id 목록", in = ParameterIn.QUERY, example = "1,2,3" - ) @RequestParam List themes + ) @RequestParam List routines ); @Operation( - summary = "테마별 데일리 루틴 목록 조회", - description = "테마에 해당되는 데일리 루틴 목록을 이름 오름차순으로 조회한다.", + summary = "데일리 루틴 달성", + description = "회원의 데일리 루틴을 달성한다.", responses = { @ApiResponse(responseCode = "200", description = "성공"), @ApiResponse( @@ -59,13 +62,13 @@ ResponseEntity> acquireAllByThe description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity> acquireAllByTheme( + SuccessResponse achieveMemberRoutine( @Parameter(hidden = true) Principal principal, @Parameter( - name = "themeId", - description = "조회할 데일리 루틴 테마 id", + name = "routineId", + description = "달성한 회원의 데일리 루틴 id", in = ParameterIn.PATH, example = "1" - ) @PathVariable long themeId + ) @PathVariable long routineId ); } diff --git a/src/main/java/com/soptie/server/api/controller/docs/MemberRoutineApiV2Docs.java b/src/main/java/com/soptie/server/api/controller/docs/MemberRoutineApiV2Docs.java new file mode 100644 index 00000000..347c4073 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/docs/MemberRoutineApiV2Docs.java @@ -0,0 +1,59 @@ +package com.soptie.server.api.controller.docs; + +import java.security.Principal; + +import org.springframework.web.bind.annotation.RequestBody; + +import com.soptie.server.api.controller.dto.request.memberroutine.CreateMemberRoutinesRequest; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.memberroutine.CreateMemberRoutinesResponse; +import com.soptie.server.api.controller.dto.response.memberroutine.GetMemberRoutinesResponse; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "MemberRoutineApi_v2", description = "회원 데일리 루틴 API version2") +public interface MemberRoutineApiV2Docs { + + @Operation( + summary = "데일리 루틴 다중 추가", + description = "회원의 데일리 루틴을 다중으로 추가한다.", + responses = { + @ApiResponse(responseCode = "201", description = "CREATED Success"), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + SuccessResponse createMemberRoutines( + @Parameter(hidden = true) Principal principal, + @RequestBody CreateMemberRoutinesRequest request + ); + + @Operation( + summary = "회원의 데일리 루틴 목록 조회", + description = "회원의 데일리 루틴 목록을 조회한다.", + responses = { + @ApiResponse(responseCode = "200", description = "OK Success"), + @ApiResponse( + responseCode = "4xx", + description = "클라이언트(요청) 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse( + responseCode = "500", + description = "서버 내부 오류", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} + ) + SuccessResponse getMemberRoutines( + @Parameter(hidden = true) Principal principal + ); +} diff --git a/src/main/java/com/soptie/server/api/controller/docs/RoutineApiDocs.java b/src/main/java/com/soptie/server/api/controller/docs/RoutineApiDocs.java new file mode 100644 index 00000000..4d40bef8 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/docs/RoutineApiDocs.java @@ -0,0 +1,51 @@ +package com.soptie.server.api.controller.docs; + +import java.security.Principal; +import java.util.LinkedHashSet; + +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.routine.GetRoutinesByMemberResponse; +import com.soptie.server.api.controller.dto.response.routine.GetRoutinesByThemeResponse; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "RoutineApi_v2", description = "데일리 루틴 API version2") +public interface RoutineApiDocs { + + @Operation( + summary = "테마 목록별 데일리 루틴 목록 조회", + description = "특정 테마 목록에 속하는 데일리 루틴 목록을 조회한다.", + responses = { + @ApiResponse(responseCode = "200", description = "OK Success") + } + ) + SuccessResponse getRoutinesByThemeIds( + @Parameter( + name = "themeIds", + description = "조회할 테마 id 목록", + required = true, + in = ParameterIn.QUERY + ) LinkedHashSet themeIds + ); + + @Operation( + summary = "테마별 데일리 루틴 목록 조회", + description = "특정 테마에 속하는 데일리 루틴 목록을 조회한다.", + responses = { + @ApiResponse(responseCode = "200", description = "OK Success") + } + ) + SuccessResponse getRoutinesByThemeId( + @Parameter(hidden = true) Principal principal, + @Parameter( + name = "themeId", + description = "조회하려는 루틴의 테마 id", + required = true, + in = ParameterIn.PATH + ) long themeId + ); +} diff --git a/src/main/java/com/soptie/server/theme/controller/v2/docs/ThemeControllerV2Docs.java b/src/main/java/com/soptie/server/api/controller/docs/ThemeApiDocs.java similarity index 56% rename from src/main/java/com/soptie/server/theme/controller/v2/docs/ThemeControllerV2Docs.java rename to src/main/java/com/soptie/server/api/controller/docs/ThemeApiDocs.java index 2ec69863..950d2a5f 100644 --- a/src/main/java/com/soptie/server/theme/controller/v2/docs/ThemeControllerV2Docs.java +++ b/src/main/java/com/soptie/server/api/controller/docs/ThemeApiDocs.java @@ -1,10 +1,8 @@ -package com.soptie.server.theme.controller.v2.docs; +package com.soptie.server.api.controller.docs; -import org.springframework.http.ResponseEntity; - -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.theme.controller.v2.dto.response.ThemeListAcquireResponse; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.theme.GetThemesResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -12,12 +10,12 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -@Tag(name = "themes-v2", description = "테마 API Version2") -public interface ThemeControllerV2Docs { +@Tag(name = "ThemeApi_v2", description = "테마 API version2") +public interface ThemeApiDocs { @Operation( summary = "테마 목록 조회", - description = "일반 테마 목록을 조회한다. (전문가 테마 미포함)", + description = "일반 테마 목록을 조회한다.", responses = { @ApiResponse(responseCode = "200", description = "성공"), @ApiResponse( @@ -29,5 +27,5 @@ public interface ThemeControllerV2Docs { description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity> acquireAllInBasic(); + SuccessResponse getBasicThemes(); } diff --git a/src/main/java/com/soptie/server/version/controller/docs/VersionControllerDocs.java b/src/main/java/com/soptie/server/api/controller/docs/VersionApiDocs.java similarity index 58% rename from src/main/java/com/soptie/server/version/controller/docs/VersionControllerDocs.java rename to src/main/java/com/soptie/server/api/controller/docs/VersionApiDocs.java index 61a2a7f2..3d102895 100644 --- a/src/main/java/com/soptie/server/version/controller/docs/VersionControllerDocs.java +++ b/src/main/java/com/soptie/server/api/controller/docs/VersionApiDocs.java @@ -1,10 +1,8 @@ -package com.soptie.server.version.controller.docs; +package com.soptie.server.api.controller.docs; -import org.springframework.http.ResponseEntity; - -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.version.controller.dto.response.AppVersionGetResponse; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.api.controller.dto.response.SuccessResponse; +import com.soptie.server.api.controller.dto.response.version.GetAppVersionResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -12,8 +10,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -@Tag(name = "versions", description = "버전 API") -public interface VersionControllerDocs { +@Tag(name = "VersionAPI", description = "버전 API") +public interface VersionApiDocs { @Operation( summary = "모바일 앱 버전 조회", @@ -25,5 +23,5 @@ public interface VersionControllerDocs { description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} ) - ResponseEntity> getClientAppVersion(); + SuccessResponse getClientAppVersion(); } diff --git a/src/main/java/com/soptie/server/api/controller/dto/request/auth/SignInRequest.java b/src/main/java/com/soptie/server/api/controller/dto/request/auth/SignInRequest.java new file mode 100644 index 00000000..a9e530df --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/request/auth/SignInRequest.java @@ -0,0 +1,14 @@ +package com.soptie.server.api.controller.dto.request.auth; + +import com.soptie.server.domain.member.SocialType; + +import jakarta.validation.constraints.NotNull; + +public record SignInRequest( + @NotNull SocialType socialType +) { + + public static SignInRequest of(SocialType socialType) { + return new SignInRequest(socialType); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/request/member/CreateProfileRequest.java b/src/main/java/com/soptie/server/api/controller/dto/request/member/CreateProfileRequest.java new file mode 100644 index 00000000..4c9f271c --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/request/member/CreateProfileRequest.java @@ -0,0 +1,18 @@ +package com.soptie.server.api.controller.dto.request.member; + +import java.util.List; + +import com.soptie.server.domain.doll.DollType; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; + +public record CreateProfileRequest( + @Schema(description = "인형 타입", example = "BROWN") + @NotNull DollType dollType, + @Schema(description = "인형 이름", example = "브라운") + @NotNull String name, + @Schema(description = "추가하려는 데일리 루틴 id 목록", example = "[1, 2, 3]") + @NotNull List routines +) { +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberMissionRequest.java b/src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberMissionRequest.java new file mode 100644 index 00000000..67d89bda --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/request/membermission/CreateMemberMissionRequest.java @@ -0,0 +1,9 @@ +package com.soptie.server.api.controller.dto.request.membermission; + +import io.swagger.v3.oas.annotations.media.Schema; + +public record CreateMemberMissionRequest( + @Schema(description = "미션(도전루틴) id", example = "1") + long subRoutineId +) { +} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/request/MemberDailyRoutinesCreateRequest.java b/src/main/java/com/soptie/server/api/controller/dto/request/memberroutine/CreateMemberRoutinesRequest.java similarity index 62% rename from src/main/java/com/soptie/server/memberroutine/controller/v1/dto/request/MemberDailyRoutinesCreateRequest.java rename to src/main/java/com/soptie/server/api/controller/dto/request/memberroutine/CreateMemberRoutinesRequest.java index a241b380..4c308ecb 100644 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/request/MemberDailyRoutinesCreateRequest.java +++ b/src/main/java/com/soptie/server/api/controller/dto/request/memberroutine/CreateMemberRoutinesRequest.java @@ -1,10 +1,10 @@ -package com.soptie.server.memberroutine.controller.v1.dto.request; +package com.soptie.server.api.controller.dto.request.memberroutine; import java.util.List; import io.swagger.v3.oas.annotations.media.Schema; -public record MemberDailyRoutinesCreateRequest( +public record CreateMemberRoutinesRequest( @Schema(description = "추가하려는 루틴 id 목록", example = "[1, 2, 3]") List routineIds ) { diff --git a/src/main/java/com/soptie/server/common/dto/BaseResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/BaseResponse.java similarity index 66% rename from src/main/java/com/soptie/server/common/dto/BaseResponse.java rename to src/main/java/com/soptie/server/api/controller/dto/response/BaseResponse.java index b54da690..670fa2a6 100644 --- a/src/main/java/com/soptie/server/common/dto/BaseResponse.java +++ b/src/main/java/com/soptie/server/api/controller/dto/response/BaseResponse.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.dto; +package com.soptie.server.api.controller.dto.response; import lombok.NonNull; diff --git a/src/main/java/com/soptie/server/common/dto/ErrorResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/ErrorResponse.java similarity index 70% rename from src/main/java/com/soptie/server/common/dto/ErrorResponse.java rename to src/main/java/com/soptie/server/api/controller/dto/response/ErrorResponse.java index c7fd422a..00dcf93b 100644 --- a/src/main/java/com/soptie/server/common/dto/ErrorResponse.java +++ b/src/main/java/com/soptie/server/api/controller/dto/response/ErrorResponse.java @@ -1,14 +1,14 @@ -package com.soptie.server.common.dto; +package com.soptie.server.api.controller.dto.response; import static lombok.AccessLevel.*; +import jakarta.validation.constraints.NotNull; import lombok.Builder; -import lombok.NonNull; @Builder(access = PRIVATE) public record ErrorResponse( boolean success, - @NonNull String message + @NotNull String message ) implements BaseResponse { public static ErrorResponse of(String message) { diff --git a/src/main/java/com/soptie/server/common/dto/SuccessResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/SuccessResponse.java similarity index 92% rename from src/main/java/com/soptie/server/common/dto/SuccessResponse.java rename to src/main/java/com/soptie/server/api/controller/dto/response/SuccessResponse.java index 8ac06219..12359ac3 100644 --- a/src/main/java/com/soptie/server/common/dto/SuccessResponse.java +++ b/src/main/java/com/soptie/server/api/controller/dto/response/SuccessResponse.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.dto; +package com.soptie.server.api.controller.dto.response; import static com.fasterxml.jackson.annotation.JsonInclude.Include.*; import static lombok.AccessLevel.*; diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/auth/SignInResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/auth/SignInResponse.java new file mode 100644 index 00000000..1b74bed4 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/auth/SignInResponse.java @@ -0,0 +1,28 @@ +package com.soptie.server.api.controller.dto.response.auth; + +import static lombok.AccessLevel.PRIVATE; + +import com.soptie.server.domain.auth.Token; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; + +@Builder(access = PRIVATE) +public record SignInResponse( + @Schema(description = "액세스 토큰") + @NotNull String accessToken, + @Schema(description = "리프레시 토큰") + @NotNull String refreshToken, + @Schema(description = "멤버 인형 존재 여부", example = "true") + boolean isMemberDollExist +) { + + public static SignInResponse of(Token token, boolean isMemberDollExist) { + return SignInResponse.builder() + .accessToken(token.getAccessToken()) + .refreshToken(token.getRefreshToken()) + .isMemberDollExist(isMemberDollExist) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/auth/TokenGetResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/auth/TokenGetResponse.java new file mode 100644 index 00000000..613d3b52 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/auth/TokenGetResponse.java @@ -0,0 +1,18 @@ +package com.soptie.server.api.controller.dto.response.auth; + +import static lombok.AccessLevel.PRIVATE; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; + +@Builder(access = PRIVATE) +public record TokenGetResponse( + @NotNull String accessToken +) { + + public static TokenGetResponse from(String accessToken) { + return TokenGetResponse.builder() + .accessToken(accessToken) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/challenge/GetChallengesByMemberResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/challenge/GetChallengesByMemberResponse.java new file mode 100644 index 00000000..a11bcacc --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/challenge/GetChallengesByMemberResponse.java @@ -0,0 +1,89 @@ +package com.soptie.server.api.controller.dto.response.challenge; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.challenge.Mission; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.val; + +@Builder(access = AccessLevel.PRIVATE) +public record GetChallengesByMemberResponse( + @Schema(description = "도전루틴 정보 목록") + @NotNull List routines +) { + + public static GetChallengesByMemberResponse of(Map>> challengeByMember) { + return GetChallengesByMemberResponse.builder() + .routines(toChallenges(challengeByMember)) + .build(); + } + + private static List toChallenges( + Map>> challengeByMember + ) { + return challengeByMember.entrySet().stream() + .map(entry -> ChallengeResponse.of(entry.getKey(), entry.getValue())) + .toList(); + } + + @Builder(access = AccessLevel.PRIVATE) + private record ChallengeResponse( + @Schema(description = "도전루틴 제목", example = "오래가는 인연을 위한 준비") + @NotNull String title, + @Schema(description = "미션 정보 목록") + @NotNull List challenges + ) { + + private static ChallengeResponse of(Challenge challenge, Map> missionsByMember) { + return ChallengeResponse.builder() + .title(challenge.getName()) + .challenges(ofMissions(missionsByMember)) + .build(); + } + + private static List ofMissions(Map> missionsByMember) { + val missions = new ArrayList(); + for (val key : missionsByMember.keySet()) { + missions.addAll(missionsByMember.get(key).stream() + .map(mission -> MissionResponse.of(mission, key)) + .toList()); + } + return missions; + } + } + + @Builder(access = AccessLevel.PRIVATE) + private record MissionResponse( + @Schema(description = "미션(도전루틴) id", example = "1") + long challengeId, + @Schema(description = "미션 내용", example = "나의 소통 방식을 파악하기") + @NotNull String content, + @Schema(description = "미션 설명", example = "이상형의 특성을 생각해보고 ...더보기") + @NotNull String description, + @Schema(description = "소요 시간", example = "5~10분") + @NotNull String requiredTime, + @Schema(description = "장소", example = "퇴근길") + @NotNull String place, + @Schema(description = "미션 추가 여부", example = "true") + boolean hasRoutine + ) { + + private static MissionResponse of(Mission mission, boolean existedInMember) { + return MissionResponse.builder() + .challengeId(mission.getId()) + .content(mission.getContent()) + .description(mission.getDescription()) + .requiredTime(mission.getRequiredTime()) + .place(mission.getPlace()) + .hasRoutine(existedInMember) + .build(); + } + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/maker/GetMakerListResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/maker/GetMakerListResponse.java new file mode 100644 index 00000000..7f828e1f --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/maker/GetMakerListResponse.java @@ -0,0 +1,59 @@ +package com.soptie.server.api.controller.dto.response.maker; + +import static lombok.AccessLevel.PRIVATE; + +import java.util.List; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; + +@Builder(access = PRIVATE) +public record GetMakerListResponse( + @Schema(description = "메아커 테마 정보 목록") + @NotNull List makers +) { + + public static GetMakerListResponse from(List response) { + return GetMakerListResponse.builder() + .makers(response.stream().map(GetMakerResponse::from).toList()) + .build(); + } + + @Builder(access = PRIVATE) + private record GetMakerResponse( + @Schema(description = "메이커 id", example = "1") + long makerId, + @Schema(description = "메이커 소개 페이지 url", example = "https://www.test") + @NotNull String introductionUrl, + @Schema(description = "메이커 이름", example = "소프티") + @NotNull String name, + @Schema(description = "메이커 프로필 이미지 url", example = "https://www.test") + @NotNull String profileImageUrl, + @Schema(description = "메이커 태그 목록", example = "[\"소프티한\", \"행복한\", \"유능한\"]") + @NotNull List tags, + @Schema(description = "테마 id", example = "1") + long themeId, + @Schema(description = "테마 설명", example = "소프티하려면 ...더보기") + @NotNull String description, + @Schema(description = "테마 이름", example = "소프티해지기") + @NotNull String themeName, + @Schema(description = "수식어", example = "200만 유튜버와 함께 하는") + @NotNull String comment + ) { + + public static GetMakerResponse from(MakerThemeResponse response) { + return GetMakerResponse.builder() + .makerId(response.maker().getId()) + .introductionUrl(response.maker().getIntroductionUrl()) + .name(response.maker().getName()) + .profileImageUrl(response.maker().getProfileImageUrl()) + .tags(response.maker().getTags().toTagList()) + .themeId(response.theme().getId()) + .description(response.theme().getDescription()) + .themeName(response.theme().getName()) + .comment(response.theme().getComment()) + .build(); + } + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/maker/MakerThemeResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/maker/MakerThemeResponse.java new file mode 100644 index 00000000..530ffd8f --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/maker/MakerThemeResponse.java @@ -0,0 +1,23 @@ +package com.soptie.server.api.controller.dto.response.maker; + +import com.querydsl.core.annotations.QueryProjection; +import com.soptie.server.domain.maker.Maker; +import com.soptie.server.domain.theme.Theme; +import com.soptie.server.persistence.entity.MakerEntity; +import com.soptie.server.persistence.entity.ThemeEntity; + +import jakarta.validation.constraints.NotNull; + +public record MakerThemeResponse( + @NotNull Theme theme, + @NotNull Maker maker +) { + + @QueryProjection + public MakerThemeResponse(ThemeEntity themeEntity, MakerEntity makerEntity) { + this( + themeEntity.toDomain(), + makerEntity.toDomain() + ); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/member/GetHomeInfoResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/member/GetHomeInfoResponse.java new file mode 100644 index 00000000..d8fb66c8 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/member/GetHomeInfoResponse.java @@ -0,0 +1,37 @@ +package com.soptie.server.api.controller.dto.response.member; + +import java.util.List; + +import com.soptie.server.domain.doll.DollType; +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.memberdoll.MemberDoll; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record GetHomeInfoResponse( + @Schema(description = "인형 이름", example = "브라운") + @NotNull String name, + @Schema(description = "인형 타입", example = "BROWN") + @NotNull DollType dollType, + @Schema(description = "일반 솜뭉치 개수", example = "10") + int dailyCottonCount, + @Schema(description = "무지개 솜뭉치 개수", example = "10") + int happinessCottonCount, + @Schema(description = "대화 내용 목록", example = "[\"안녕?\", \"반가워~\"]") + @NotNull List conversations +) { + + public static GetHomeInfoResponse of(Member member, MemberDoll memberDoll, List conversations) { + return GetHomeInfoResponse.builder() + .name(memberDoll.getName()) + .dollType(memberDoll.getDollType()) + .dailyCottonCount(member.getCottonInfo().getBasicCottonCount()) + .happinessCottonCount(member.getCottonInfo().getRainbowCottonCount()) + .conversations(conversations) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/member/GiveMemberCottonResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/member/GiveMemberCottonResponse.java new file mode 100644 index 00000000..e05d3873 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/member/GiveMemberCottonResponse.java @@ -0,0 +1,29 @@ +package com.soptie.server.api.controller.dto.response.member; + +import com.soptie.server.domain.member.CottonType; +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.member.MemberCotton; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record GiveMemberCottonResponse( + @Schema(description = "회원의 솜뭉치 개수", example = "5") + int cottonCount +) { + + public static GiveMemberCottonResponse of(Member member, CottonType cottonType) { + return GiveMemberCottonResponse.builder() + .cottonCount(getCottonCount(member.getCottonInfo(), cottonType)) + .build(); + } + + private static int getCottonCount(MemberCotton cotton, CottonType cottonType) { + return switch (cottonType) { + case DAILY -> cotton.getBasicCottonCount(); + case HAPPINESS -> cotton.getRainbowCottonCount(); + }; + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberMissionResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberMissionResponse.java new file mode 100644 index 00000000..b56368fa --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/CreateMemberMissionResponse.java @@ -0,0 +1,20 @@ +package com.soptie.server.api.controller.dto.response.membermission; + +import com.soptie.server.domain.membermission.MemberMission; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record CreateMemberMissionResponse( + @Schema(description = "추가한 회원의 미션 id", example = "1") + long routineId +) { + + public static CreateMemberMissionResponse of(MemberMission memberMission) { + return CreateMemberMissionResponse.builder() + .routineId(memberMission.getId()) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/membermission/GetMemberMissionResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/GetMemberMissionResponse.java new file mode 100644 index 00000000..c28298ca --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/membermission/GetMemberMissionResponse.java @@ -0,0 +1,44 @@ +package com.soptie.server.api.controller.dto.response.membermission; + +import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.domain.challenge.Mission; +import com.soptie.server.domain.theme.Theme; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record GetMemberMissionResponse( + @Schema(description = "미션(도전루틴) id", example = "1") + long routineId, + @Schema(description = "테마 id", example = "1") + long themeId, + @Schema(description = "테마 이름", example = "관계 쌓기") + @NotNull String themeName, + @Schema(description = "도전 이름", example = "오래가는 인연을 위한 준비") + @NotNull String title, + @Schema(description = "미션 내용", example = "일어나면 5분 안에 이불 개기") + @NotNull String content, + @Schema(description = "미션 상세 내용", example = "평소에 바빠서 ...더보기") + @NotNull String detailContent, + @Schema(description = "장소", example = "침대") + @NotNull String place, + @Schema(description = "소요시간", example = "3분") + @NotNull String timeTaken +) { + + public static GetMemberMissionResponse of(Theme theme, Challenge challenge, Mission mission) { + return GetMemberMissionResponse.builder() + .routineId(mission.getId()) + .themeId(theme.getId()) + .themeName(theme.getName()) + .title(challenge.getName()) + .content(mission.getContent()) + .detailContent(mission.getDescription()) + .place(mission.getPlace()) + .timeTaken(mission.getRequiredTime()) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/memberroutine/AchieveMemberRoutineResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/memberroutine/AchieveMemberRoutineResponse.java new file mode 100644 index 00000000..377abaef --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/memberroutine/AchieveMemberRoutineResponse.java @@ -0,0 +1,29 @@ +package com.soptie.server.api.controller.dto.response.memberroutine; + +import com.soptie.server.domain.memberroutine.MemberRoutine; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record AchieveMemberRoutineResponse( + @Schema(description = "달성 업데이트한 회원의 루틴 id", example = "1") + long routineId, + @Schema(description = "달성 여부", example = "true") + boolean isAchieve, + @Schema(description = "달성 횟수", example = "10") + int achieveCount, + @Schema(description = "솜뭉치 획득 여부", example = "true") + boolean hasCotton +) { + + public static AchieveMemberRoutineResponse of(MemberRoutine memberRoutine, boolean isAcquiredCotton) { + return AchieveMemberRoutineResponse.builder() + .routineId(memberRoutine.getRoutineId()) + .isAchieve(memberRoutine.isAchieved()) + .achieveCount(memberRoutine.getAchievementCount()) + .hasCotton(isAcquiredCotton) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/memberroutine/CreateMemberRoutinesResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/memberroutine/CreateMemberRoutinesResponse.java new file mode 100644 index 00000000..4b6b7791 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/memberroutine/CreateMemberRoutinesResponse.java @@ -0,0 +1,23 @@ +package com.soptie.server.api.controller.dto.response.memberroutine; + +import java.util.List; + +import com.soptie.server.domain.memberroutine.MemberRoutine; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.NonNull; + +@Builder(access = AccessLevel.PRIVATE) +public record CreateMemberRoutinesResponse( + @Schema(description = "추가한 회원 루틴 id 목록", example = "[1, 2, 3]") + @NonNull List ids +) { + + public static CreateMemberRoutinesResponse of(List routines) { + return CreateMemberRoutinesResponse.builder() + .ids(routines.stream().map(MemberRoutine::getId).toList()) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/memberroutine/GetMemberRoutinesResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/memberroutine/GetMemberRoutinesResponse.java new file mode 100644 index 00000000..a1169150 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/memberroutine/GetMemberRoutinesResponse.java @@ -0,0 +1,81 @@ +package com.soptie.server.api.controller.dto.response.memberroutine; + +import java.util.List; +import java.util.Map; + +import com.soptie.server.domain.memberroutine.MemberRoutine; +import com.soptie.server.domain.routine.Routine; +import com.soptie.server.domain.theme.Theme; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record GetMemberRoutinesResponse( + @Schema(description = "회원의 루틴 정보 목록") + @NotNull List routines +) { + + public static GetMemberRoutinesResponse of(Map> routinesByTheme) { + return GetMemberRoutinesResponse.builder() + .routines(toMemberRoutines(routinesByTheme)) + .build(); + } + + private static List toMemberRoutines( + Map> routinesByTheme + ) { + return routinesByTheme.entrySet().stream() + .map(entry -> MemberRoutinesResponse.of(entry.getKey(), entry.getValue())) + .toList(); + } + + @Builder(access = AccessLevel.PRIVATE) + public record MemberRoutinesResponse( + @Schema(description = "테마 id", example = "1") + long themeId, + @Schema(description = "테마 이름", example = "관계 쌓기") + @NotNull String themeName, + @Schema(description = "루틴 정보 목록") + @NotNull List routines + ) { + + public static MemberRoutinesResponse of(Theme theme, Map routinesByMember) { + return MemberRoutinesResponse.builder() + .themeId(theme.getId()) + .themeName(theme.getName()) + .routines(toRoutines(routinesByMember)) + .build(); + } + + private static List toRoutines(Map routinesByMember) { + return routinesByMember.entrySet().stream() + .map(entry -> MemberRoutineResponse.of(entry.getKey(), entry.getValue())) + .toList(); + } + + @Builder(access = AccessLevel.PRIVATE) + public record MemberRoutineResponse( + @Schema(description = "회원 루틴 id", example = "1") + long routineId, + @Schema(description = "루틴 내용", example = "밥 먹기") + @NotNull String content, + @Schema(description = "달성 횟수", example = "10") + int achieveCount, + @Schema(description = "달성 여부", example = "true") + boolean isAchieve + ) { + + private static MemberRoutineResponse of(Routine routine, MemberRoutine memberRoutine) { + return MemberRoutineResponse.builder() + .routineId(memberRoutine.getId()) + .content(routine.getContent()) + .achieveCount(memberRoutine.getAchievementCount()) + .isAchieve(memberRoutine.isAchieved()) + .build(); + } + } + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/routine/GetRoutinesByMemberResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/routine/GetRoutinesByMemberResponse.java new file mode 100644 index 00000000..e0c33b42 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/routine/GetRoutinesByMemberResponse.java @@ -0,0 +1,55 @@ +package com.soptie.server.api.controller.dto.response.routine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.soptie.server.domain.routine.Routine; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.val; + +@Builder(access = AccessLevel.PRIVATE) +public record GetRoutinesByMemberResponse( + @Schema(description = "조회하려는 루틴 목록") + @NotNull List routines +) { + + public static GetRoutinesByMemberResponse of(Map> routineToMember) { + return GetRoutinesByMemberResponse.builder() + .routines(ofRoutines(routineToMember)) + .build(); + } + + private static List ofRoutines(Map> routineToMember) { + val routines = new ArrayList(); + for (val key : routineToMember.keySet()) { + routines.addAll(routineToMember.get(key).stream() + .map(routine -> RoutineResponse.of(routine, key)) + .toList()); + } + return routines; + } + + @Builder(access = AccessLevel.PRIVATE) + private record RoutineResponse( + @Schema(description = "루틴 id", example = "1") + long id, + @Schema(description = "루틴 내용", example = "놀러가기") + @NotNull String content, + @Schema(description = "회원이 가지고 있는 루틴 유무", example = "true") + boolean existedInMember + ) { + + private static RoutineResponse of(Routine routine, boolean existedInMember) { + return RoutineResponse.builder() + .id(routine.getId()) + .content(routine.getContent()) + .existedInMember(existedInMember) + .build(); + } + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/routine/GetRoutinesByThemeResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/routine/GetRoutinesByThemeResponse.java new file mode 100644 index 00000000..ea833917 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/routine/GetRoutinesByThemeResponse.java @@ -0,0 +1,62 @@ +package com.soptie.server.api.controller.dto.response.routine; + +import java.util.List; +import java.util.Map; + +import com.soptie.server.domain.routine.Routine; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record GetRoutinesByThemeResponse( + @Schema(description = "테마 정보 목록") + List themes +) { + + public static GetRoutinesByThemeResponse of(Map> routinesByThemeId) { + return GetRoutinesByThemeResponse.builder() + .themes(ofThemes(routinesByThemeId)) + .build(); + } + + private static List ofThemes(Map> routinesByThemeId) { + return routinesByThemeId.keySet().stream() + .map(key -> ThemeResponse.of(key, routinesByThemeId.get(key))) + .toList(); + } + + @Builder(access = AccessLevel.PRIVATE) + private record ThemeResponse( + @Schema(description = "테마 id", example = "1") + long themeId, + @Schema(description = "루틴 정보 목록") + List routines + ) { + + private static ThemeResponse of(long themeId, List routines) { + return ThemeResponse.builder() + .themeId(themeId) + .routines(routines.stream().map(RoutineResponse::of).toList()) + .build(); + } + } + + @Builder(access = AccessLevel.PRIVATE) + private record RoutineResponse( + @Schema(description = "루틴 id", example = "1") + long routineId, + @Schema(description = "루틴 내용", example = "1일 1커밋하기") + @NotNull String content + ) { + + private static RoutineResponse of(Routine routine) { + return RoutineResponse.builder() + .routineId(routine.getId()) + .content(routine.getContent()) + .build(); + } + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/theme/GetThemesResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/theme/GetThemesResponse.java new file mode 100644 index 00000000..f7216d7d --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/theme/GetThemesResponse.java @@ -0,0 +1,45 @@ +package com.soptie.server.api.controller.dto.response.theme; + +import java.util.List; + +import com.soptie.server.domain.theme.Theme; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record GetThemesResponse( + @Schema(description = "테마 정보 목록") + @NotNull List themes +) { + + public static GetThemesResponse of(List themes) { + return GetThemesResponse.builder() + .themes(themes.stream().map(ThemeResponse::of).toList()) + .build(); + } + + @Builder(access = AccessLevel.PRIVATE) + private record ThemeResponse( + @Schema(description = "테마 id", example = "1") + long themeId, + @Schema(description = "테마 이름", example = "관계 쌓기") + @NotNull String title, + @Schema(description = "테마 코멘트", example = "사람들과 어울리는") + @NotNull String subTitle, + @Schema(description = "테마 설명", example = "행복은 흔히 관계에서 온다고 해 ...더보기") + @NotNull String description + ) { + + private static ThemeResponse of(Theme theme) { + return ThemeResponse.builder() + .themeId(theme.getId()) + .title(theme.getName()) + .subTitle(theme.getComment()) + .description(theme.getDescription()) + .build(); + } + } +} diff --git a/src/main/java/com/soptie/server/api/controller/dto/response/version/GetAppVersionResponse.java b/src/main/java/com/soptie/server/api/controller/dto/response/version/GetAppVersionResponse.java new file mode 100644 index 00000000..68073430 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/dto/response/version/GetAppVersionResponse.java @@ -0,0 +1,48 @@ +package com.soptie.server.api.controller.dto.response.version; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record GetAppVersionResponse( + @Schema(description = "iOS 버전 정보") + VersionResponse iosVersion, + @Schema(description = "Android 버전 정보") + VersionResponse androidVersion, + @Schema(description = "업데이트 안내 제목", example = "업데이트 알림") + String notificationTitle, + @Schema(description = "업데이트 안내 내용", example = "업데이트하세요.") + String notificationContent +) { + + public static GetAppVersionResponse of( + String iosAppVersion, + String iosAppForceVersion, + String androidAppVersion, + String androidAppForceVersion, + String notificationTitle, + String notificationContent + ) { + return GetAppVersionResponse.builder() + .iosVersion(VersionResponse.of(iosAppVersion, iosAppForceVersion)) + .androidVersion(VersionResponse.of(androidAppVersion, androidAppForceVersion)) + .notificationTitle(notificationTitle) + .notificationContent(notificationContent) + .build(); + } + + @Builder(access = AccessLevel.PRIVATE) + private record VersionResponse( + String appVersion, + String forceUpdateVersion + ) { + + private static VersionResponse of(String appVersion, String forceUpdateVersion) { + return VersionResponse.builder() + .appVersion(appVersion) + .forceUpdateVersion(forceUpdateVersion) + .build(); + } + } +} diff --git a/src/main/java/com/soptie/server/api/controller/generic/SuccessMessage.java b/src/main/java/com/soptie/server/api/controller/generic/SuccessMessage.java new file mode 100644 index 00000000..14e197a4 --- /dev/null +++ b/src/main/java/com/soptie/server/api/controller/generic/SuccessMessage.java @@ -0,0 +1,39 @@ +package com.soptie.server.api.controller.generic; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum SuccessMessage { + /* auth */ + SUCCESS_SIGN_IN("로그인 성공"), + SUCCESS_RECREATE_TOKEN("토큰 재발급 성공"), + SUCCESS_SIGN_OUT("로그아웃 성공"), + SUCCESS_WITHDRAWAL("회원 탈퇴 성공"), + + /* member */ + CREATE_MEMBER_PROFILE("회원 프로필 등록 성공"), + GIVE_COTTON("솜뭉치 주기 성공"), + GET_MEMBER_HOME("홈화면 정보 조회 성공"), + + /* theme */ + GET_THEME("테마 조회 성공"), + + /* routine */ + CREATE_ROUTINE("루틴 추가 성공"), + GET_ROUTINE("루틴 조회 성공"), + ACHIEVE_ROUTINE("루틴 달성 성공"), + DELETE_ROUTINE("루틴 삭제 성공"), + + /* challenge */ + GET_CHALLENGE("도전루틴 조회 성공"), + + /* maker */ + SUCCESS_GET_MAKER_THEME("메이커 테마 조회 성공"), + + /* version */ + GET_VERSION("버전 조회 성공"); + + private final String message; +} diff --git a/src/main/java/com/soptie/server/api/web/advice/ErrorHandler.java b/src/main/java/com/soptie/server/api/web/advice/ErrorHandler.java new file mode 100644 index 00000000..d98d6d15 --- /dev/null +++ b/src/main/java/com/soptie/server/api/web/advice/ErrorHandler.java @@ -0,0 +1,32 @@ +package com.soptie.server.api.web.advice; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.common.exception.SoftieException; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestControllerAdvice +public class ErrorHandler { + + @ExceptionHandler(SoftieException.class) + public ResponseEntity authException(SoftieException exception) { + log.error(exception.getMessage()); + return ResponseEntity + .status(exception.getStatusCode()) + .body(ErrorResponse.of(exception.getDefaultMessage() + "\n" + exception.getDetailMessage())); + } + + @ExceptionHandler(RuntimeException.class) + public ResponseEntity makerException(RuntimeException exception) { + log.error(exception.getMessage()); + return ResponseEntity + .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) + .body(ErrorResponse.of(exception.getMessage())); + } +} diff --git a/src/main/java/com/soptie/server/auth/jwt/CustomJwtAuthenticationEntryPoint.java b/src/main/java/com/soptie/server/api/web/jwt/CustomJwtAuthenticationEntryPoint.java similarity index 78% rename from src/main/java/com/soptie/server/auth/jwt/CustomJwtAuthenticationEntryPoint.java rename to src/main/java/com/soptie/server/api/web/jwt/CustomJwtAuthenticationEntryPoint.java index 1f35e168..8da22ecf 100644 --- a/src/main/java/com/soptie/server/auth/jwt/CustomJwtAuthenticationEntryPoint.java +++ b/src/main/java/com/soptie/server/api/web/jwt/CustomJwtAuthenticationEntryPoint.java @@ -1,6 +1,5 @@ -package com.soptie.server.auth.jwt; +package com.soptie.server.api.web.jwt; -import static com.soptie.server.auth.message.ErrorCode.*; import static jakarta.servlet.http.HttpServletResponse.*; import static org.springframework.http.MediaType.*; @@ -11,7 +10,8 @@ import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; -import com.soptie.server.common.dto.ErrorResponse; +import com.soptie.server.api.controller.dto.response.ErrorResponse; +import com.soptie.server.common.exception.ExceptionCode; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -36,6 +36,7 @@ private void setResponse(HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); response.setContentType(APPLICATION_JSON_VALUE); response.setStatus(SC_UNAUTHORIZED); - response.getWriter().println(objectMapper.writeValueAsString(ErrorResponse.of(INVALID_TOKEN.getMessage()))); + response.getWriter() + .println(objectMapper.writeValueAsString(ErrorResponse.of(ExceptionCode.UNAUTHORIZED.getMessage()))); } } diff --git a/src/main/java/com/soptie/server/auth/jwt/JwtAuthenticationFilter.java b/src/main/java/com/soptie/server/api/web/jwt/JwtAuthenticationFilter.java similarity index 93% rename from src/main/java/com/soptie/server/auth/jwt/JwtAuthenticationFilter.java rename to src/main/java/com/soptie/server/api/web/jwt/JwtAuthenticationFilter.java index d5c86f26..bd054309 100644 --- a/src/main/java/com/soptie/server/auth/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/soptie/server/api/web/jwt/JwtAuthenticationFilter.java @@ -1,6 +1,5 @@ -package com.soptie.server.auth.jwt; +package com.soptie.server.api.web.jwt; -import static com.soptie.server.auth.jwt.JwtValidationType.*; import static io.jsonwebtoken.lang.Strings.*; import static org.springframework.http.HttpHeaders.*; @@ -11,7 +10,7 @@ import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; -import com.soptie.server.common.config.ValueConfig; +import com.soptie.server.common.support.ValueConfig; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; @@ -33,7 +32,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse FilterChain filterChain) throws ServletException, IOException { try { val token = getAccessTokenFromRequest(request); - if (hasText(token) && jwtTokenProvider.validateToken(token) == VALID_JWT) { + if (hasText(token) && jwtTokenProvider.validateToken(token) == JwtValidationType.VALID_JWT) { val authentication = new UserAuthentication(getMemberId(token), null, null); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); diff --git a/src/main/java/com/soptie/server/auth/jwt/JwtTokenProvider.java b/src/main/java/com/soptie/server/api/web/jwt/JwtTokenProvider.java similarity index 87% rename from src/main/java/com/soptie/server/auth/jwt/JwtTokenProvider.java rename to src/main/java/com/soptie/server/api/web/jwt/JwtTokenProvider.java index 19e50450..3ca6bfda 100644 --- a/src/main/java/com/soptie/server/auth/jwt/JwtTokenProvider.java +++ b/src/main/java/com/soptie/server/api/web/jwt/JwtTokenProvider.java @@ -1,6 +1,5 @@ -package com.soptie.server.auth.jwt; +package com.soptie.server.api.web.jwt; -import static com.soptie.server.auth.jwt.JwtValidationType.*; import static io.jsonwebtoken.Header.*; import static io.jsonwebtoken.security.Keys.*; import static java.util.Base64.*; @@ -12,7 +11,7 @@ import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; -import com.soptie.server.common.config.ValueConfig; +import com.soptie.server.common.support.ValueConfig; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; @@ -43,19 +42,19 @@ public String generateToken(Authentication authentication, long expiration) { public JwtValidationType validateToken(String token) { try { getBody(token); - return VALID_JWT; + return JwtValidationType.VALID_JWT; } catch (MalformedJwtException exception) { log.error(exception.getMessage()); - return INVALID_JWT_TOKEN; + return JwtValidationType.INVALID_JWT_TOKEN; } catch (ExpiredJwtException exception) { log.error(exception.getMessage()); - return EXPIRED_JWT_TOKEN; + return JwtValidationType.EXPIRED_JWT_TOKEN; } catch (UnsupportedJwtException exception) { log.error(exception.getMessage()); - return UNSUPPORTED_JWT_TOKEN; + return JwtValidationType.UNSUPPORTED_JWT_TOKEN; } catch (IllegalArgumentException exception) { log.error(exception.getMessage()); - return EMPTY_JWT; + return JwtValidationType.EMPTY_JWT; } } diff --git a/src/main/java/com/soptie/server/auth/jwt/JwtValidationType.java b/src/main/java/com/soptie/server/api/web/jwt/JwtValidationType.java similarity index 75% rename from src/main/java/com/soptie/server/auth/jwt/JwtValidationType.java rename to src/main/java/com/soptie/server/api/web/jwt/JwtValidationType.java index e82cb971..9e7ce394 100644 --- a/src/main/java/com/soptie/server/auth/jwt/JwtValidationType.java +++ b/src/main/java/com/soptie/server/api/web/jwt/JwtValidationType.java @@ -1,4 +1,4 @@ -package com.soptie.server.auth.jwt; +package com.soptie.server.api.web.jwt; public enum JwtValidationType { VALID_JWT, diff --git a/src/main/java/com/soptie/server/auth/jwt/UserAuthentication.java b/src/main/java/com/soptie/server/api/web/jwt/UserAuthentication.java similarity index 91% rename from src/main/java/com/soptie/server/auth/jwt/UserAuthentication.java rename to src/main/java/com/soptie/server/api/web/jwt/UserAuthentication.java index 7d98bf12..c9e62e05 100644 --- a/src/main/java/com/soptie/server/auth/jwt/UserAuthentication.java +++ b/src/main/java/com/soptie/server/api/web/jwt/UserAuthentication.java @@ -1,4 +1,4 @@ -package com.soptie.server.auth.jwt; +package com.soptie.server.api.web.jwt; import java.util.Collection; diff --git a/src/main/java/com/soptie/server/auth/controller/AuthController.java b/src/main/java/com/soptie/server/auth/controller/AuthController.java deleted file mode 100644 index de648edc..00000000 --- a/src/main/java/com/soptie/server/auth/controller/AuthController.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.soptie.server.auth.controller; - -import static com.soptie.server.auth.message.SuccessMessage.*; -import static com.soptie.server.common.dto.SuccessResponse.*; - -import java.security.Principal; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.auth.controller.docs.AuthControllerDocs; -import com.soptie.server.auth.controller.dto.request.SignInRequest; -import com.soptie.server.auth.controller.dto.response.SignInResponse; -import com.soptie.server.auth.controller.dto.response.TokenGetResponse; -import com.soptie.server.auth.service.AuthService; -import com.soptie.server.auth.service.dto.request.SignInServiceRequest; -import com.soptie.server.auth.service.dto.request.TokenGetServiceRequest; -import com.soptie.server.common.dto.BaseResponse; -import com.soptie.server.common.dto.SuccessResponse; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/auth") -public class AuthController implements AuthControllerDocs { - - private final AuthService authService; - - @PostMapping - public ResponseEntity> signIn( - @RequestHeader("Authorization") String socialAccessToken, - @RequestBody SignInRequest request - ) { - val response = SignInResponse.of(authService.signIn(SignInServiceRequest.of(socialAccessToken, request))); - return ResponseEntity.ok(success(SUCCESS_SIGN_IN.getMessage(), response)); - } - - @PostMapping("/token") - public ResponseEntity> reissueToken( - @RequestHeader("Authorization") String refreshToken - ) { - val response = TokenGetResponse.of(authService.reissueToken(TokenGetServiceRequest.of(refreshToken))); - return ResponseEntity.ok(success(SUCCESS_RECREATE_TOKEN.getMessage(), response)); - } - - @PostMapping("/logout") - public ResponseEntity signOut(Principal principal) { - val memberId = Long.parseLong(principal.getName()); - authService.signOut(memberId); - return ResponseEntity.ok(success(SUCCESS_SIGN_OUT.getMessage())); - } - - @DeleteMapping - public ResponseEntity withdrawal(Principal principal) { - val memberId = Long.parseLong(principal.getName()); - authService.withdraw(memberId); - return ResponseEntity.ok(success(SUCCESS_WITHDRAWAL.getMessage())); - } -} diff --git a/src/main/java/com/soptie/server/auth/controller/dto/request/SignInRequest.java b/src/main/java/com/soptie/server/auth/controller/dto/request/SignInRequest.java deleted file mode 100644 index 113872f4..00000000 --- a/src/main/java/com/soptie/server/auth/controller/dto/request/SignInRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.soptie.server.auth.controller.dto.request; - -import com.soptie.server.member.entity.SocialType; - -import lombok.NonNull; - -public record SignInRequest( - @NonNull SocialType socialType -) { - - public static SignInRequest of(SocialType socialType) { - return new SignInRequest(socialType); - } -} diff --git a/src/main/java/com/soptie/server/auth/controller/dto/response/SignInResponse.java b/src/main/java/com/soptie/server/auth/controller/dto/response/SignInResponse.java deleted file mode 100644 index 6523ff76..00000000 --- a/src/main/java/com/soptie/server/auth/controller/dto/response/SignInResponse.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.soptie.server.auth.controller.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.auth.service.dto.response.SignInServiceResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record SignInResponse( - @NonNull String accessToken, - @NonNull String refreshToken, - boolean isMemberDollExist -) { - - public static SignInResponse of(SignInServiceResponse response) { - return SignInResponse.builder() - .accessToken(response.accessToken()) - .refreshToken(response.refreshToken()) - .isMemberDollExist(response.isMemberDollExist()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/auth/controller/dto/response/TokenGetResponse.java b/src/main/java/com/soptie/server/auth/controller/dto/response/TokenGetResponse.java deleted file mode 100644 index daa06cd7..00000000 --- a/src/main/java/com/soptie/server/auth/controller/dto/response/TokenGetResponse.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.soptie.server.auth.controller.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.auth.service.dto.response.TokenGetServiceResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record TokenGetResponse( - @NonNull String accessToken -) { - - public static TokenGetResponse of(TokenGetServiceResponse response) { - return TokenGetResponse.builder() - .accessToken(response.accessToken()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/auth/exception/AuthException.java b/src/main/java/com/soptie/server/auth/exception/AuthException.java deleted file mode 100644 index 189342c2..00000000 --- a/src/main/java/com/soptie/server/auth/exception/AuthException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.auth.exception; - -import com.soptie.server.auth.message.ErrorCode; - -import lombok.Getter; - -@Getter -public class AuthException extends RuntimeException { - - private final ErrorCode errorCode; - - public AuthException(ErrorCode errorCode) { - super("[AuthException] : " + errorCode.getMessage()); - this.errorCode = errorCode; - } -} diff --git a/src/main/java/com/soptie/server/auth/message/ErrorCode.java b/src/main/java/com/soptie/server/auth/message/ErrorCode.java deleted file mode 100644 index ee7e51fb..00000000 --- a/src/main/java/com/soptie/server/auth/message/ErrorCode.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.soptie.server.auth.message; - -import static org.springframework.http.HttpStatus.*; - -import org.springframework.http.HttpStatus; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public enum ErrorCode { - - /* 401 UNAUTHORIZED : 권한 없음 */ - INVALID_TOKEN(UNAUTHORIZED, "유효하지 않은 토큰입니다."), - INVALID_KEY(UNAUTHORIZED, "유효하지 않은 키입니다."); - - private final HttpStatus httpStatus; - private final String message; -} diff --git a/src/main/java/com/soptie/server/auth/message/SuccessMessage.java b/src/main/java/com/soptie/server/auth/message/SuccessMessage.java deleted file mode 100644 index eb2d0d43..00000000 --- a/src/main/java/com/soptie/server/auth/message/SuccessMessage.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.auth.message; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum SuccessMessage { - - SUCCESS_SIGN_IN("소셜로그인 성공"), - SUCCESS_RECREATE_TOKEN("토큰 재발급 성공"), - SUCCESS_SIGN_OUT("로그아웃 성공"), - SUCCESS_WITHDRAWAL("회원 탈퇴 성공"); - - private final String message; -} diff --git a/src/main/java/com/soptie/server/auth/service/AuthService.java b/src/main/java/com/soptie/server/auth/service/AuthService.java deleted file mode 100644 index d7b40822..00000000 --- a/src/main/java/com/soptie/server/auth/service/AuthService.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soptie.server.auth.service; - -import com.soptie.server.auth.service.dto.request.SignInServiceRequest; -import com.soptie.server.auth.service.dto.request.TokenGetServiceRequest; -import com.soptie.server.auth.service.dto.response.SignInServiceResponse; -import com.soptie.server.auth.service.dto.response.TokenGetServiceResponse; - -public interface AuthService { - - SignInServiceResponse signIn(SignInServiceRequest request); - - void signOut(long memberId); - - void withdraw(long memberId); - - TokenGetServiceResponse reissueToken(TokenGetServiceRequest request); -} diff --git a/src/main/java/com/soptie/server/auth/service/AuthServiceImpl.java b/src/main/java/com/soptie/server/auth/service/AuthServiceImpl.java deleted file mode 100644 index 55b37519..00000000 --- a/src/main/java/com/soptie/server/auth/service/AuthServiceImpl.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.soptie.server.auth.service; - -import static com.soptie.server.member.message.ErrorCode.*; - -import java.util.Objects; - -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.auth.jwt.JwtTokenProvider; -import com.soptie.server.auth.jwt.UserAuthentication; -import com.soptie.server.auth.service.dto.request.SignInServiceRequest; -import com.soptie.server.auth.service.dto.request.TokenGetServiceRequest; -import com.soptie.server.auth.service.dto.response.SignInServiceResponse; -import com.soptie.server.auth.service.dto.response.TokenGetServiceResponse; -import com.soptie.server.auth.vo.Token; -import com.soptie.server.common.config.ValueConfig; -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.entity.SocialType; -import com.soptie.server.member.exception.MemberException; -import com.soptie.server.member.repository.MemberRepository; -import com.soptie.server.member.service.MemberService; -import com.soptie.server.memberdoll.entity.MemberDoll; -import com.soptie.server.memberdoll.service.MemberDollService; -import com.soptie.server.memberroutine.adapter.MemberRoutineDeleter; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class AuthServiceImpl implements AuthService { - - private final JwtTokenProvider jwtTokenProvider; - private final MemberRepository memberRepository; - private final KakaoService kakaoService; - private final AppleService appleService; - private final MemberService memberService; - private final MemberDollService memberDollService; - private final ValueConfig valueConfig; - - private final MemberRoutineDeleter memberRoutineDeleter; - - @Override - @Transactional - public SignInServiceResponse signIn(SignInServiceRequest request) { - val member = getMember(request.socialAccessToken(), request.socialType()); - val token = getToken(member); - val isMemberDollExist = member.isMemberDollExist(); - return SignInServiceResponse.of(token, isMemberDollExist); - } - - @Override - public TokenGetServiceResponse reissueToken(TokenGetServiceRequest request) { - val member = findMember(request.refreshToken()); - val token = generateAccessToken(member.getId()); - return TokenGetServiceResponse.of(token); - } - - @Override - @Transactional - public void signOut(long memberId) { - val member = findMember(memberId); - member.resetRefreshToken(); - } - - @Override - @Transactional - public void withdraw(long memberId) { - val member = findMember(memberId); - deleteMemberDoll(member.getMemberDoll()); - memberRoutineDeleter.deleteByMember(member); - deleteMember(member); - } - - private Member getMember(String socialAccessToken, SocialType socialType) { - val socialId = getSocialId(socialAccessToken, socialType); - return signUp(socialType, socialId); - } - - private String getSocialId(String socialAccessToken, SocialType socialType) { - return switch (socialType) { - case APPLE -> appleService.getAppleData(socialAccessToken); - case KAKAO -> kakaoService.getKakaoData(socialAccessToken); - }; - } - - private Member signUp(SocialType socialType, String socialId) { - return memberRepository.findBySocialTypeAndSocialId(socialType, socialId) - .orElseGet(() -> saveMember(socialType, socialId)); - } - - private Member saveMember(SocialType socialType, String socialId) { - val member = Member.builder().socialType(socialType).socialId(socialId).build(); - return memberRepository.save(member); - } - - private Token getToken(Member member) { - val token = generateToken(new UserAuthentication(member.getId(), null, null)); - member.updateRefreshToken(token.getRefreshToken()); - return token; - } - - private Token generateToken(Authentication authentication) { - return Token.builder() - .accessToken(jwtTokenProvider.generateToken(authentication, valueConfig.getAccessTokenExpired())) - .refreshToken(jwtTokenProvider.generateToken(authentication, valueConfig.getRefreshTokenExpired())) - .build(); - } - - private Member findMember(long id) { - return memberRepository.findById(id).orElseThrow(() -> new MemberException(INVALID_MEMBER)); - } - - private Member findMember(String refreshToken) { - return memberRepository.findByRefreshToken(getTokenFromBearerString(refreshToken)) - .orElseThrow(() -> new MemberException(INVALID_MEMBER)); - } - - private String getTokenFromBearerString(String token) { - return token.replaceFirst(ValueConfig.BEARER_HEADER, ValueConfig.BLANK); - } - - private String generateAccessToken(long memberId) { - val authentication = new UserAuthentication(memberId, null, null); - return jwtTokenProvider.generateToken(authentication, valueConfig.getAccessTokenExpired()); - } - - private void deleteMemberDoll(MemberDoll memberDoll) { - if (Objects.nonNull(memberDoll)) { - memberDollService.deleteMemberDoll(memberDoll); - } - } - - private void deleteMember(Member member) { - memberService.deleteMember(member); - } -} diff --git a/src/main/java/com/soptie/server/auth/service/dto/request/SignInServiceRequest.java b/src/main/java/com/soptie/server/auth/service/dto/request/SignInServiceRequest.java deleted file mode 100644 index 4997649c..00000000 --- a/src/main/java/com/soptie/server/auth/service/dto/request/SignInServiceRequest.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.soptie.server.auth.service.dto.request; - -import static lombok.AccessLevel.*; - -import com.soptie.server.auth.controller.dto.request.SignInRequest; -import com.soptie.server.member.entity.SocialType; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record SignInServiceRequest( - @NonNull String socialAccessToken, - @NonNull SocialType socialType -) { - - public static SignInServiceRequest of(String socialAccessToken, SignInRequest request) { - return SignInServiceRequest.builder() - .socialAccessToken(socialAccessToken) - .socialType(request.socialType()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/auth/service/dto/request/TokenGetServiceRequest.java b/src/main/java/com/soptie/server/auth/service/dto/request/TokenGetServiceRequest.java deleted file mode 100644 index d0e4a215..00000000 --- a/src/main/java/com/soptie/server/auth/service/dto/request/TokenGetServiceRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.soptie.server.auth.service.dto.request; - -import static lombok.AccessLevel.*; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record TokenGetServiceRequest( - @NonNull String refreshToken -) { - - public static TokenGetServiceRequest of(String refreshToken) { - return TokenGetServiceRequest.builder() - .refreshToken(refreshToken) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/auth/service/dto/response/SignInServiceResponse.java b/src/main/java/com/soptie/server/auth/service/dto/response/SignInServiceResponse.java deleted file mode 100644 index a92b02e1..00000000 --- a/src/main/java/com/soptie/server/auth/service/dto/response/SignInServiceResponse.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.soptie.server.auth.service.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.auth.vo.Token; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record SignInServiceResponse( - @NonNull String accessToken, - @NonNull String refreshToken, - boolean isMemberDollExist -) { - - public static SignInServiceResponse of(Token token, boolean isMemberDollExist) { - return SignInServiceResponse.builder() - .accessToken(token.getAccessToken()) - .refreshToken(token.getRefreshToken()) - .isMemberDollExist(isMemberDollExist) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/auth/service/dto/response/TokenGetServiceResponse.java b/src/main/java/com/soptie/server/auth/service/dto/response/TokenGetServiceResponse.java deleted file mode 100644 index f8754ce7..00000000 --- a/src/main/java/com/soptie/server/auth/service/dto/response/TokenGetServiceResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.soptie.server.auth.service.dto.response; - -import static lombok.AccessLevel.*; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record TokenGetServiceResponse( - @NonNull String accessToken -) { - - public static TokenGetServiceResponse of(String accessToken) { - return TokenGetServiceResponse.builder() - .accessToken(accessToken) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/scheduler/MemberDailyRoutineScheduler.java b/src/main/java/com/soptie/server/batch/MemberRoutineScheduler.java similarity index 56% rename from src/main/java/com/soptie/server/memberroutine/scheduler/MemberDailyRoutineScheduler.java rename to src/main/java/com/soptie/server/batch/MemberRoutineScheduler.java index 6846cd5c..a20c3d25 100644 --- a/src/main/java/com/soptie/server/memberroutine/scheduler/MemberDailyRoutineScheduler.java +++ b/src/main/java/com/soptie/server/batch/MemberRoutineScheduler.java @@ -1,22 +1,21 @@ -package com.soptie.server.memberroutine.scheduler; +package com.soptie.server.batch; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import com.soptie.server.memberroutine.service.MemberRoutineUpdateService; +import com.soptie.server.domain.memberroutine.MemberRoutineService; import lombok.RequiredArgsConstructor; @Component @EnableScheduling @RequiredArgsConstructor -public class MemberDailyRoutineScheduler { - - private final MemberRoutineUpdateService memberRoutineUpdateService; +public class MemberRoutineScheduler { + private final MemberRoutineService memberRoutineService; @Scheduled(cron = "${softie.cron.init.routine}") public void initMemberDailyRoutines() { - memberRoutineUpdateService.initDailyRoutines(); + memberRoutineService.initAchievement(); } } diff --git a/src/main/java/com/soptie/server/common/exception/ExceptionCode.java b/src/main/java/com/soptie/server/common/exception/ExceptionCode.java new file mode 100644 index 00000000..0c28a7fd --- /dev/null +++ b/src/main/java/com/soptie/server/common/exception/ExceptionCode.java @@ -0,0 +1,20 @@ +package com.soptie.server.common.exception; + +import org.springframework.http.HttpStatus; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +public enum ExceptionCode { + /* 4xx */ + BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청"), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "권한 없음"), + NOT_FOUND(HttpStatus.NOT_FOUND, "찾을 수 없는 리소스"), + NOT_AVAILABLE(HttpStatus.NOT_ACCEPTABLE, "접근할 수 없는 리소스"); + + private final HttpStatus httpStatus; + private final String message; +} diff --git a/src/main/java/com/soptie/server/common/exception/SoftieException.java b/src/main/java/com/soptie/server/common/exception/SoftieException.java new file mode 100644 index 00000000..4fbab79d --- /dev/null +++ b/src/main/java/com/soptie/server/common/exception/SoftieException.java @@ -0,0 +1,24 @@ +package com.soptie.server.common.exception; + +import lombok.Getter; + +@Getter +public class SoftieException extends RuntimeException { + private final int statusCode; + private final String defaultMessage; + private final String detailMessage; + + public SoftieException(ExceptionCode exceptionCode) { + super("[" + exceptionCode.getHttpStatus() + "] " + exceptionCode.getMessage()); + this.statusCode = exceptionCode.getHttpStatus().value(); + this.defaultMessage = exceptionCode.getMessage(); + this.detailMessage = null; + } + + public SoftieException(ExceptionCode exceptionCode, String detailMessage) { + super("[" + exceptionCode.getHttpStatus() + "] " + exceptionCode.getMessage()); + this.statusCode = exceptionCode.getHttpStatus().value(); + this.defaultMessage = exceptionCode.getMessage(); + this.detailMessage = detailMessage; + } +} diff --git a/src/main/java/com/soptie/server/common/handler/ErrorHandler.java b/src/main/java/com/soptie/server/common/handler/ErrorHandler.java deleted file mode 100644 index 2b4229a4..00000000 --- a/src/main/java/com/soptie/server/common/handler/ErrorHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.soptie.server.common.handler; - -import static com.soptie.server.common.dto.ErrorResponse.of; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import com.soptie.server.auth.exception.AuthException; -import com.soptie.server.common.dto.BaseResponse; -import com.soptie.server.doll.exception.DollException; -import com.soptie.server.maker.exception.MakerException; -import com.soptie.server.member.exception.MemberException; -import com.soptie.server.memberdoll.exception.MemberDollException; -import com.soptie.server.routine.exception.RoutineException; -import com.soptie.server.theme.exception.ThemeException; - -import lombok.extern.slf4j.Slf4j; -import lombok.val; - -@Slf4j -@RestControllerAdvice -public class ErrorHandler { - - @ExceptionHandler(AuthException.class) - public ResponseEntity authException(AuthException exception) { - log.error(exception.getMessage()); - - val errorCode = exception.getErrorCode(); - return ResponseEntity.status(errorCode.getHttpStatus()).body(of(errorCode.getMessage())); - } - - @ExceptionHandler(DollException.class) - public ResponseEntity dollException(DollException exception) { - log.error(exception.getMessage()); - - val errorCode = exception.getErrorCode(); - return ResponseEntity.status(errorCode.getHttpStatus()).body(of(errorCode.getMessage())); - } - - @ExceptionHandler(MemberException.class) - public ResponseEntity memberException(MemberException exception) { - log.error(exception.getMessage()); - - val errorCode = exception.getErrorCode(); - return ResponseEntity.status(errorCode.getHttpStatus()).body(of(errorCode.getMessage())); - } - - @ExceptionHandler(MemberDollException.class) - public ResponseEntity memberDollException(MemberDollException exception) { - log.error(exception.getMessage()); - - val errorCode = exception.getErrorCode(); - return ResponseEntity.status(errorCode.getHttpStatus()).body(of(errorCode.getMessage())); - } - - @ExceptionHandler(RoutineException.class) - public ResponseEntity routineException(RoutineException exception) { - log.error(exception.getMessage()); - - val errorCode = exception.getErrorCode(); - return ResponseEntity.status(errorCode.getHttpStatus()).body(of(errorCode.getMessage())); - } - - @ExceptionHandler(ThemeException.class) - public ResponseEntity routineException(ThemeException exception) { - log.error(exception.getMessage()); - - val errorCode = exception.getErrorCode(); - return ResponseEntity.status(errorCode.getHttpStatus()).body(of(errorCode.getMessage())); - } - - @ExceptionHandler(MakerException.class) - public ResponseEntity makerException(MakerException exception) { - log.error(exception.getMessage()); - - val errorCode = exception.getErrorCode(); - return ResponseEntity.status(errorCode.getHttpStatus()).body(of(errorCode.getMessage())); - } -} diff --git a/src/main/java/com/soptie/server/common/support/StringListConverter.java b/src/main/java/com/soptie/server/common/support/StringListConverter.java deleted file mode 100644 index fd931c5d..00000000 --- a/src/main/java/com/soptie/server/common/support/StringListConverter.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.soptie.server.common.support; - -import static java.util.Collections.emptyList; - -import java.util.Arrays; -import java.util.List; - -import jakarta.persistence.AttributeConverter; -import jakarta.persistence.Converter; - -@Converter -public class StringListConverter implements AttributeConverter, String> { - - private static final String SPLIT_CHAR = ","; - - @Override - public String convertToDatabaseColumn(List attribute) { - return attribute != null ? String.join(SPLIT_CHAR, attribute) : ""; - } - - @Override - public List convertToEntityAttribute(String dbData) { - return dbData != null ? Arrays.asList(dbData.split(SPLIT_CHAR)) : emptyList(); - } -} diff --git a/src/main/java/com/soptie/server/common/support/UriGenerator.java b/src/main/java/com/soptie/server/common/support/UriGenerator.java deleted file mode 100644 index c75991fc..00000000 --- a/src/main/java/com/soptie/server/common/support/UriGenerator.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.soptie.server.common.support; - -import java.net.URI; - -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; - -@Component -public class UriGenerator { - - public static URI getUri(String path, long id) { - return ServletUriComponentsBuilder - .fromCurrentRequest() - .path(path + id) - .buildAndExpand() - .toUri(); - } - - public static URI getUri(String path) { - return ServletUriComponentsBuilder - .fromCurrentRequest() - .path(path) - .buildAndExpand() - .toUri(); - } -} diff --git a/src/main/java/com/soptie/server/common/config/ValueConfig.java b/src/main/java/com/soptie/server/common/support/ValueConfig.java similarity index 97% rename from src/main/java/com/soptie/server/common/config/ValueConfig.java rename to src/main/java/com/soptie/server/common/support/ValueConfig.java index 280dc509..d9420f4a 100644 --- a/src/main/java/com/soptie/server/common/config/ValueConfig.java +++ b/src/main/java/com/soptie/server/common/support/ValueConfig.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.config; +package com.soptie.server.common.support; import java.nio.charset.StandardCharsets; import java.util.Base64; diff --git a/src/main/java/com/soptie/server/conversation/adapter/ConversationFinder.java b/src/main/java/com/soptie/server/conversation/adapter/ConversationFinder.java deleted file mode 100644 index f24cc7fc..00000000 --- a/src/main/java/com/soptie/server/conversation/adapter/ConversationFinder.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.soptie.server.conversation.adapter; - -import java.util.List; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.conversation.entity.Conversation; -import com.soptie.server.conversation.repository.ConversationRepository; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class ConversationFinder { - - private final ConversationRepository conversationRepository; - - public List findAll() { - return conversationRepository.findAll(); - } -} diff --git a/src/main/java/com/soptie/server/conversation/entity/Conversation.java b/src/main/java/com/soptie/server/conversation/entity/Conversation.java deleted file mode 100644 index c6e4e9ed..00000000 --- a/src/main/java/com/soptie/server/conversation/entity/Conversation.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.soptie.server.conversation.entity; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -@Getter -public class Conversation { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "conversation_id") - private Long id; - - private String content; - - public Conversation(Long id, String content) { - this.id = id; - this.content = content; - } -} diff --git a/src/main/java/com/soptie/server/conversation/repository/ConversationRepository.java b/src/main/java/com/soptie/server/conversation/repository/ConversationRepository.java deleted file mode 100644 index 01ca328b..00000000 --- a/src/main/java/com/soptie/server/conversation/repository/ConversationRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soptie.server.conversation.repository; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.conversation.entity.Conversation; - -public interface ConversationRepository extends JpaRepository { -} diff --git a/src/main/java/com/soptie/server/doll/adapter/DollFinder.java b/src/main/java/com/soptie/server/doll/adapter/DollFinder.java deleted file mode 100644 index aa20923b..00000000 --- a/src/main/java/com/soptie/server/doll/adapter/DollFinder.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.soptie.server.doll.adapter; - -import static com.soptie.server.doll.message.ErrorCode.*; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.doll.exception.DollException; -import com.soptie.server.doll.repository.DollRepository; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class DollFinder { - - private final DollRepository dollRepository; - - public Doll findByType(DollType type) { - return dollRepository.findByDollType(type) - .orElseThrow(() -> new DollException(INVALID_TYPE)); - } -} diff --git a/src/main/java/com/soptie/server/doll/controller/DollController.java b/src/main/java/com/soptie/server/doll/controller/DollController.java deleted file mode 100644 index 704d40ad..00000000 --- a/src/main/java/com/soptie/server/doll/controller/DollController.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.soptie.server.doll.controller; - -import static com.soptie.server.common.dto.SuccessResponse.*; -import static com.soptie.server.doll.message.SuccessMessage.*; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.doll.controller.docs.DollControllerDocs; -import com.soptie.server.doll.dto.DollImageResponse; -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.doll.service.DollService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/dolls") -public class DollController implements DollControllerDocs { - - private final DollService dollService; - - @GetMapping("/image/{type}") - public ResponseEntity> getDollImages(@PathVariable DollType type) { - val response = dollService.getDollImage(type); - return ResponseEntity.ok(success(SUCCESS_GET_IMAGE.getMessage(), response)); - } -} diff --git a/src/main/java/com/soptie/server/doll/controller/docs/DollControllerDocs.java b/src/main/java/com/soptie/server/doll/controller/docs/DollControllerDocs.java deleted file mode 100644 index 254abb4a..00000000 --- a/src/main/java/com/soptie/server/doll/controller/docs/DollControllerDocs.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.soptie.server.doll.controller.docs; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; - -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.doll.dto.DollImageResponse; -import com.soptie.server.doll.entity.DollType; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "dolls", description = "애착 인형 API") -public interface DollControllerDocs { - - @Operation( - summary = "인형 이미지 불러오기", - description = "인형 이미지를 불러온다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "400", - description = "유효하지 않은 인형 타입", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity> getDollImages( - @Parameter( - name = "type", - description = "인형 타입", - in = ParameterIn.PATH, - example = "BROWN" - ) @PathVariable DollType type - ); -} diff --git a/src/main/java/com/soptie/server/doll/dto/DollImageResponse.java b/src/main/java/com/soptie/server/doll/dto/DollImageResponse.java deleted file mode 100644 index 86a1d478..00000000 --- a/src/main/java/com/soptie/server/doll/dto/DollImageResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.soptie.server.doll.dto; - -import com.soptie.server.doll.entity.Doll; - -import lombok.NonNull; - -public record DollImageResponse( - @NonNull String faceImageUrl -) { - - public static DollImageResponse of(Doll doll) { - return new DollImageResponse(doll.getImageLinks().getFaceImageUrl()); - } -} diff --git a/src/main/java/com/soptie/server/doll/entity/Doll.java b/src/main/java/com/soptie/server/doll/entity/Doll.java deleted file mode 100644 index a421caba..00000000 --- a/src/main/java/com/soptie/server/doll/entity/Doll.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.soptie.server.doll.entity; - -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -@Getter -public class Doll { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "doll_id") - private Long id; - - @Enumerated(value = EnumType.STRING) - private DollType dollType; - - @Embedded - private DollImageLinks imageLinks; - - public Doll(DollType dollType, DollImageLinks imageLinks) { - this.dollType = dollType; - this.imageLinks = imageLinks; - } - - public Doll(Long id, DollType dollType, String faceImageUrl) { - this.id = id; - this.dollType = dollType; - this.imageLinks = new DollImageLinks(faceImageUrl, "", ""); - } -} diff --git a/src/main/java/com/soptie/server/doll/entity/DollImageLinks.java b/src/main/java/com/soptie/server/doll/entity/DollImageLinks.java deleted file mode 100644 index ad9efd28..00000000 --- a/src/main/java/com/soptie/server/doll/entity/DollImageLinks.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.soptie.server.doll.entity; - -import static lombok.AccessLevel.*; - -import jakarta.persistence.Embeddable; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Embeddable -@NoArgsConstructor -@AllArgsConstructor(access = PACKAGE) -@Getter -public class DollImageLinks { - - private String faceImageUrl; - - private String attentionImageUrl; - - private String frameImageUrl; -} diff --git a/src/main/java/com/soptie/server/doll/exception/DollException.java b/src/main/java/com/soptie/server/doll/exception/DollException.java deleted file mode 100644 index d0d8abdb..00000000 --- a/src/main/java/com/soptie/server/doll/exception/DollException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.doll.exception; - -import com.soptie.server.doll.message.ErrorCode; - -import lombok.Getter; - -@Getter -public class DollException extends RuntimeException { - - private final ErrorCode errorCode; - - public DollException(ErrorCode errorCode) { - super("[DollException] : " + errorCode.getMessage()); - this.errorCode = errorCode; - } -} diff --git a/src/main/java/com/soptie/server/doll/message/ErrorCode.java b/src/main/java/com/soptie/server/doll/message/ErrorCode.java deleted file mode 100644 index 66fc32da..00000000 --- a/src/main/java/com/soptie/server/doll/message/ErrorCode.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.soptie.server.doll.message; - -import static org.springframework.http.HttpStatus.*; - -import org.springframework.http.HttpStatus; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public enum ErrorCode { - - /* 400 BAD_REQUEST : 잘못된 요청 */ - INVALID_TYPE(BAD_REQUEST, "유효하지 않은 인형 타입입니다."), - INVALID_NAME(BAD_REQUEST, "조건에 맞지 않는 이름입니다."); - - private final HttpStatus httpStatus; - private final String message; -} diff --git a/src/main/java/com/soptie/server/doll/message/SuccessMessage.java b/src/main/java/com/soptie/server/doll/message/SuccessMessage.java deleted file mode 100644 index e8c05d49..00000000 --- a/src/main/java/com/soptie/server/doll/message/SuccessMessage.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soptie.server.doll.message; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum SuccessMessage { - - SUCCESS_GET_IMAGE("인형 이미지 조회 성공"); - - private final String message; -} diff --git a/src/main/java/com/soptie/server/doll/repository/DollRepository.java b/src/main/java/com/soptie/server/doll/repository/DollRepository.java deleted file mode 100644 index c35ce03d..00000000 --- a/src/main/java/com/soptie/server/doll/repository/DollRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.soptie.server.doll.repository; - -import java.util.Optional; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.doll.entity.DollType; - -public interface DollRepository extends JpaRepository { - Optional findByDollType(DollType type); -} diff --git a/src/main/java/com/soptie/server/doll/service/DollService.java b/src/main/java/com/soptie/server/doll/service/DollService.java deleted file mode 100644 index c2fa9e8b..00000000 --- a/src/main/java/com/soptie/server/doll/service/DollService.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soptie.server.doll.service; - -import com.soptie.server.doll.dto.DollImageResponse; -import com.soptie.server.doll.entity.DollType; - -public interface DollService { - DollImageResponse getDollImage(DollType type); -} diff --git a/src/main/java/com/soptie/server/doll/service/DollServiceImpl.java b/src/main/java/com/soptie/server/doll/service/DollServiceImpl.java deleted file mode 100644 index f7f492b8..00000000 --- a/src/main/java/com/soptie/server/doll/service/DollServiceImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.soptie.server.doll.service; - -import static com.soptie.server.doll.message.ErrorCode.*; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.doll.dto.DollImageResponse; -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.doll.exception.DollException; -import com.soptie.server.doll.repository.DollRepository; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class DollServiceImpl implements DollService { - - private final DollRepository dollRepository; - - @Override - public DollImageResponse getDollImage(DollType type) { - val doll = findDoll(type); - return DollImageResponse.of(doll); - } - - private Doll findDoll(DollType type) { - return dollRepository.findByDollType(type) - .orElseThrow(() -> new DollException(INVALID_TYPE)); - } -} diff --git a/src/main/java/com/soptie/server/domain/auth/AuthService.java b/src/main/java/com/soptie/server/domain/auth/AuthService.java new file mode 100644 index 00000000..0f5ad307 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/auth/AuthService.java @@ -0,0 +1,113 @@ +package com.soptie.server.domain.auth; + +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.soptie.server.api.controller.dto.request.auth.SignInRequest; +import com.soptie.server.api.controller.dto.response.auth.SignInResponse; +import com.soptie.server.api.controller.dto.response.auth.TokenGetResponse; +import com.soptie.server.api.web.jwt.JwtTokenProvider; +import com.soptie.server.api.web.jwt.UserAuthentication; +import com.soptie.server.common.support.ValueConfig; +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.member.SocialType; +import com.soptie.server.external.oauth.AppleService; +import com.soptie.server.external.oauth.KakaoService; +import com.soptie.server.persistence.adapter.MemberAdapter; +import com.soptie.server.persistence.adapter.MemberDollAdapter; +import com.soptie.server.persistence.adapter.MemberMissionAdapter; +import com.soptie.server.persistence.adapter.MemberRoutineAdapter; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class AuthService { + + private final JwtTokenProvider jwtTokenProvider; + private final KakaoService kakaoService; + private final AppleService appleService; + private final ValueConfig valueConfig; + + private final MemberDollAdapter memberDollAdapter; + private final MemberRoutineAdapter memberRoutineAdapter; + private final MemberMissionAdapter memberMissionAdapter; + private final MemberAdapter memberAdapter; + + @Transactional + public SignInResponse signIn(String socialAccessToken, SignInRequest request) { + val member = getMember(socialAccessToken, request.socialType()); + val token = getToken(member); + val isMemberDollExist = memberDollAdapter.isExistByMember(member.getId()); + memberAdapter.update(member); + return SignInResponse.of(token, isMemberDollExist); + } + + public TokenGetResponse reissueToken(String refreshToken) { + val member = memberAdapter.findByRefreshToken(getTokenFromBearerString(refreshToken)); + val token = generateAccessToken(member.getId()); + return TokenGetResponse.from(token); + } + + @Transactional + public void signOut(long memberId) { + val member = memberAdapter.findById(memberId); + member.resetRefreshToken(); + memberAdapter.update(member); + } + + @Transactional + public void withdraw(long memberId) { + memberAdapter.findById(memberId); + memberRoutineAdapter.deleteAllByMemberId(memberId); + memberMissionAdapter.deleteAllByMemberId(memberId); + memberDollAdapter.deleteByMember(memberId); + memberAdapter.delete(memberId); + } + + private Member getMember(String socialAccessToken, SocialType socialType) { + val socialId = getSocialId(socialAccessToken, socialType); + return signUp(socialType, socialId); + } + + private String getSocialId(String socialAccessToken, SocialType socialType) { + return switch (socialType) { + case APPLE -> appleService.getAppleData(socialAccessToken); + case KAKAO -> kakaoService.getKakaoData(socialAccessToken); + }; + } + + private Member signUp(SocialType socialType, String socialId) { + return memberAdapter.findBySocialTypeAndSocialId(socialType, socialId) + .orElseGet(() -> saveMember(socialType, socialId)); + } + + private Member saveMember(SocialType socialType, String socialId) { + return memberAdapter.save(socialType, socialId); + } + + private Token getToken(Member member) { + val token = generateToken(new UserAuthentication(member.getId(), null, null)); + member.updateRefreshToken(token.getRefreshToken()); + return token; + } + + private Token generateToken(Authentication authentication) { + return Token.builder() + .accessToken(jwtTokenProvider.generateToken(authentication, valueConfig.getAccessTokenExpired())) + .refreshToken(jwtTokenProvider.generateToken(authentication, valueConfig.getRefreshTokenExpired())) + .build(); + } + + private String getTokenFromBearerString(String token) { + return token.replaceFirst(ValueConfig.BEARER_HEADER, ValueConfig.BLANK); + } + + private String generateAccessToken(long memberId) { + val authentication = new UserAuthentication(memberId, null, null); + return jwtTokenProvider.generateToken(authentication, valueConfig.getAccessTokenExpired()); + } +} diff --git a/src/main/java/com/soptie/server/auth/vo/Token.java b/src/main/java/com/soptie/server/domain/auth/Token.java similarity index 94% rename from src/main/java/com/soptie/server/auth/vo/Token.java rename to src/main/java/com/soptie/server/domain/auth/Token.java index b2fde336..14b97c40 100644 --- a/src/main/java/com/soptie/server/auth/vo/Token.java +++ b/src/main/java/com/soptie/server/domain/auth/Token.java @@ -1,4 +1,4 @@ -package com.soptie.server.auth.vo; +package com.soptie.server.domain.auth; import java.util.Objects; diff --git a/src/main/java/com/soptie/server/domain/challenge/Challenge.java b/src/main/java/com/soptie/server/domain/challenge/Challenge.java new file mode 100644 index 00000000..ee5e9fc5 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/challenge/Challenge.java @@ -0,0 +1,14 @@ +package com.soptie.server.domain.challenge; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Challenge { + private Long id; + @NotNull + private String name; + private long themeId; +} diff --git a/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java b/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java new file mode 100644 index 00000000..327265cb --- /dev/null +++ b/src/main/java/com/soptie/server/domain/challenge/ChallengeService.java @@ -0,0 +1,53 @@ +package com.soptie.server.domain.challenge; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.soptie.server.api.controller.dto.response.challenge.GetChallengesByMemberResponse; +import com.soptie.server.domain.membermission.MemberMission; +import com.soptie.server.persistence.adapter.ChallengeAdapter; +import com.soptie.server.persistence.adapter.MemberMissionAdapter; +import com.soptie.server.persistence.adapter.MissionAdapter; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class ChallengeService { + private final ChallengeAdapter challengeAdapter; + private final MissionAdapter missionAdapter; + private final MemberMissionAdapter memberMissionAdapter; + + public GetChallengesByMemberResponse getChallengesByTheme(long memberId, long themeId) { + val challenges = challengeAdapter.findByThemeId(themeId); + val missions = missionAdapter.findByChallengeIds(challenges.stream().map(Challenge::getId).toList()); + val missionIds = missions.stream().map(Mission::getId).toList(); + val memberMissionIds = memberMissionAdapter.findByMemberIdAndMissionIds(memberId, missionIds).stream() + .map(MemberMission::getMissionId) + .toList(); + return GetChallengesByMemberResponse.of(toChallengesByMember(challenges, missions, memberMissionIds)); + } + + private Map>> toChallengesByMember( + List challenges, + List missions, + List memberMissionIds + ) { + return challenges.stream().collect(Collectors.toMap( + // challenge-key + challenge -> challenge, + // map-value + challenge -> missions.stream() + .filter(mission -> mission.getChallengeId() == challenge.getId()) + .collect(Collectors.partitioningBy( // missionId in memberMissionIds 조건에 따라 true/false 분류 + mission -> memberMissionIds.contains(mission.getId()) + )) + )); + } +} diff --git a/src/main/java/com/soptie/server/domain/challenge/Mission.java b/src/main/java/com/soptie/server/domain/challenge/Mission.java new file mode 100644 index 00000000..c403f91d --- /dev/null +++ b/src/main/java/com/soptie/server/domain/challenge/Mission.java @@ -0,0 +1,20 @@ +package com.soptie.server.domain.challenge; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Mission { + private Long id; + @NotNull + private String content; + @NotNull + private String description; + @NotNull + private String requiredTime; + @NotNull + private String place; + private long challengeId; +} diff --git a/src/main/java/com/soptie/server/domain/conversation/Conversation.java b/src/main/java/com/soptie/server/domain/conversation/Conversation.java new file mode 100644 index 00000000..943ea29b --- /dev/null +++ b/src/main/java/com/soptie/server/domain/conversation/Conversation.java @@ -0,0 +1,13 @@ +package com.soptie.server.domain.conversation; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Conversation { + private Long id; + @NotNull + private String content; +} diff --git a/src/main/java/com/soptie/server/domain/doll/Doll.java b/src/main/java/com/soptie/server/domain/doll/Doll.java new file mode 100644 index 00000000..bfb36ba6 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/doll/Doll.java @@ -0,0 +1,13 @@ +package com.soptie.server.domain.doll; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Doll { + Long id; + @NotNull + DollType type; +} diff --git a/src/main/java/com/soptie/server/doll/entity/DollType.java b/src/main/java/com/soptie/server/domain/doll/DollType.java similarity index 56% rename from src/main/java/com/soptie/server/doll/entity/DollType.java rename to src/main/java/com/soptie/server/domain/doll/DollType.java index 84b3e960..61a1d61c 100644 --- a/src/main/java/com/soptie/server/doll/entity/DollType.java +++ b/src/main/java/com/soptie/server/domain/doll/DollType.java @@ -1,4 +1,4 @@ -package com.soptie.server.doll.entity; +package com.soptie.server.domain.doll; public enum DollType { BROWN, GRAY, RED, WHITE diff --git a/src/main/java/com/soptie/server/domain/maker/Maker.java b/src/main/java/com/soptie/server/domain/maker/Maker.java new file mode 100644 index 00000000..f1638edd --- /dev/null +++ b/src/main/java/com/soptie/server/domain/maker/Maker.java @@ -0,0 +1,17 @@ +package com.soptie.server.domain.maker; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Maker { + private Long id; + @NotNull + private String name; + private String introductionUrl; + private String profileImageUrl; + @NotNull + private Tags tags; +} diff --git a/src/main/java/com/soptie/server/domain/maker/MakerService.java b/src/main/java/com/soptie/server/domain/maker/MakerService.java new file mode 100644 index 00000000..1dee2bd3 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/maker/MakerService.java @@ -0,0 +1,23 @@ +package com.soptie.server.domain.maker; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.soptie.server.api.controller.dto.response.maker.GetMakerListResponse; +import com.soptie.server.persistence.adapter.ThemeAdapter; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MakerService { + + private final ThemeAdapter themeAdapter; + + public GetMakerListResponse acquireAll() { + val themes = themeAdapter.findAllWithMaker(); + return GetMakerListResponse.from(themes); + } +} diff --git a/src/main/java/com/soptie/server/domain/maker/Tags.java b/src/main/java/com/soptie/server/domain/maker/Tags.java new file mode 100644 index 00000000..9fc457fb --- /dev/null +++ b/src/main/java/com/soptie/server/domain/maker/Tags.java @@ -0,0 +1,30 @@ +package com.soptie.server.domain.maker; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import lombok.Getter; + +@Getter +public class Tags { + private final String contents; + + private static final String TAG_SEPARATE = ","; + + public Tags(String tags) { + this.contents = tags; + } + + public Tags(List tags) { + this.contents = String.join(TAG_SEPARATE, tags); + } + + public List toTagList() { + return hasContents() ? Arrays.stream(contents.split(TAG_SEPARATE)).toList() : new ArrayList<>(); + } + + private boolean hasContents() { + return contents != null && !contents.isEmpty(); + } +} diff --git a/src/main/java/com/soptie/server/member/entity/CottonType.java b/src/main/java/com/soptie/server/domain/member/CottonType.java similarity index 53% rename from src/main/java/com/soptie/server/member/entity/CottonType.java rename to src/main/java/com/soptie/server/domain/member/CottonType.java index 18afed4a..9651aef4 100644 --- a/src/main/java/com/soptie/server/member/entity/CottonType.java +++ b/src/main/java/com/soptie/server/domain/member/CottonType.java @@ -1,4 +1,4 @@ -package com.soptie.server.member.entity; +package com.soptie.server.domain.member; public enum CottonType { DAILY, diff --git a/src/main/java/com/soptie/server/domain/member/Member.java b/src/main/java/com/soptie/server/domain/member/Member.java new file mode 100644 index 00000000..f7877f9d --- /dev/null +++ b/src/main/java/com/soptie/server/domain/member/Member.java @@ -0,0 +1,21 @@ +package com.soptie.server.domain.member; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Member { + private Long id; + private Social socialInfo; + private String refreshToken; + private MemberCotton cottonInfo; + + public void resetRefreshToken() { + this.refreshToken = null; + } + + public void updateRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + } +} diff --git a/src/main/java/com/soptie/server/domain/member/MemberCotton.java b/src/main/java/com/soptie/server/domain/member/MemberCotton.java new file mode 100644 index 00000000..1c8a415e --- /dev/null +++ b/src/main/java/com/soptie/server/domain/member/MemberCotton.java @@ -0,0 +1,26 @@ +package com.soptie.server.domain.member; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class MemberCotton { + protected int basicCottonCount; + protected int rainbowCottonCount; + + public void addBasicCottonCount() { + this.basicCottonCount++; + } + + public void addRainbowCottonCount() { + this.rainbowCottonCount++; + } + + public void subtractCotton(CottonType type) { + switch (type) { + case DAILY -> basicCottonCount--; + case HAPPINESS -> rainbowCottonCount--; + } + } +} diff --git a/src/main/java/com/soptie/server/domain/member/MemberService.java b/src/main/java/com/soptie/server/domain/member/MemberService.java new file mode 100644 index 00000000..c40db71b --- /dev/null +++ b/src/main/java/com/soptie/server/domain/member/MemberService.java @@ -0,0 +1,73 @@ +package com.soptie.server.domain.member; + +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.soptie.server.api.controller.dto.request.member.CreateProfileRequest; +import com.soptie.server.api.controller.dto.response.member.GetHomeInfoResponse; +import com.soptie.server.api.controller.dto.response.member.GiveMemberCottonResponse; +import com.soptie.server.domain.conversation.Conversation; +import com.soptie.server.domain.doll.DollType; +import com.soptie.server.domain.memberdoll.MemberDoll; +import com.soptie.server.persistence.adapter.ConversationAdapter; +import com.soptie.server.persistence.adapter.DollAdapter; +import com.soptie.server.persistence.adapter.MemberAdapter; +import com.soptie.server.persistence.adapter.MemberDollAdapter; +import com.soptie.server.persistence.adapter.MemberRoutineAdapter; +import com.soptie.server.persistence.adapter.RoutineAdapter; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MemberService { + private final MemberAdapter memberAdapter; + private final ConversationAdapter conversationAdapter; + private final DollAdapter dollAdapter; + private final RoutineAdapter routineAdapter; + private final MemberDollAdapter memberDollAdapter; + private final MemberRoutineAdapter memberRoutineAdapter; + + @Transactional + public void createMemberProfile(long memberId, CreateProfileRequest request) { + val member = memberAdapter.findById(memberId); + createMemberDoll(memberId, request.dollType(), request.name()); + createMemberRoutines(member, request.routines()); + } + + @Transactional + public GiveMemberCottonResponse giveCotton(long memberId, CottonType cottonType) { + val member = memberAdapter.findById(memberId); + member.getCottonInfo().subtractCotton(cottonType); + memberAdapter.update(member); + + val memberDoll = memberDollAdapter.findByMember(memberId); + memberDoll.getCottonInfo().giveCotton(cottonType); + memberDollAdapter.update(memberDoll); + + return GiveMemberCottonResponse.of(member, cottonType); + } + + public GetHomeInfoResponse getMemberHomeInfo(long memberId) { + val member = memberAdapter.findById(memberId); + val memberDoll = memberDollAdapter.findByMember(memberId); + val conversations = conversationAdapter.findAll().stream().map(Conversation::getContent).toList(); + return GetHomeInfoResponse.of(member, memberDoll, conversations); + } + + private void createMemberRoutines(Member member, List routineIds) { + val routines = routineAdapter.findByIds(routineIds); + memberRoutineAdapter.saveAll(member, routines); + } + + private void createMemberDoll(long memberId, DollType dollType, String name) { + if (!memberDollAdapter.isExistByMember(memberId)) { + val doll = dollAdapter.findByType(dollType); + memberDollAdapter.save(new MemberDoll(name, dollType, memberId, doll.getId())); + } + } +} diff --git a/src/main/java/com/soptie/server/domain/member/Social.java b/src/main/java/com/soptie/server/domain/member/Social.java new file mode 100644 index 00000000..90f3a942 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/member/Social.java @@ -0,0 +1,12 @@ +package com.soptie.server.domain.member; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; + +@Builder +public class Social { + @NotNull + protected SocialType socialType; + @NotNull + protected String socialId; +} diff --git a/src/main/java/com/soptie/server/member/entity/SocialType.java b/src/main/java/com/soptie/server/domain/member/SocialType.java similarity index 50% rename from src/main/java/com/soptie/server/member/entity/SocialType.java rename to src/main/java/com/soptie/server/domain/member/SocialType.java index b1900063..df72f0d7 100644 --- a/src/main/java/com/soptie/server/member/entity/SocialType.java +++ b/src/main/java/com/soptie/server/domain/member/SocialType.java @@ -1,4 +1,4 @@ -package com.soptie.server.member.entity; +package com.soptie.server.domain.member; public enum SocialType { KAKAO, APPLE diff --git a/src/main/java/com/soptie/server/domain/memberdoll/DollCotton.java b/src/main/java/com/soptie/server/domain/memberdoll/DollCotton.java new file mode 100644 index 00000000..1e049184 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/memberdoll/DollCotton.java @@ -0,0 +1,20 @@ +package com.soptie.server.domain.memberdoll; + +import com.soptie.server.domain.member.CottonType; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class DollCotton { + private int basicCottonCount; + private int rainbowCottonCount; + + public void giveCotton(CottonType type) { + switch (type) { + case DAILY -> basicCottonCount++; + case HAPPINESS -> rainbowCottonCount++; + } + } +} diff --git a/src/main/java/com/soptie/server/domain/memberdoll/MemberDoll.java b/src/main/java/com/soptie/server/domain/memberdoll/MemberDoll.java new file mode 100644 index 00000000..4d117f56 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/memberdoll/MemberDoll.java @@ -0,0 +1,31 @@ +package com.soptie.server.domain.memberdoll; + +import com.soptie.server.domain.doll.DollType; + +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Builder +@AllArgsConstructor +@Getter +public class MemberDoll { + private Long id; + @NotNull + private DollType dollType; + @NotNull + private String name; + @NotNull + private DollCotton cottonInfo; + private long memberId; + private long dollId; + + public MemberDoll(String name, DollType dollType, long memberId, long dollId) { + this.name = name; + this.dollType = dollType; + this.cottonInfo = new DollCotton(0, 0); + this.memberId = memberId; + this.dollId = dollId; + } +} diff --git a/src/main/java/com/soptie/server/domain/membermission/MemberMission.java b/src/main/java/com/soptie/server/domain/membermission/MemberMission.java new file mode 100644 index 00000000..fdb6f549 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/membermission/MemberMission.java @@ -0,0 +1,17 @@ +package com.soptie.server.domain.membermission; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class MemberMission { + private Long id; + private int achievementCount; + private long memberId; + private long missionId; + + public void achieve() { + this.achievementCount++; + } +} diff --git a/src/main/java/com/soptie/server/domain/membermission/MemberMissionService.java b/src/main/java/com/soptie/server/domain/membermission/MemberMissionService.java new file mode 100644 index 00000000..b9908dec --- /dev/null +++ b/src/main/java/com/soptie/server/domain/membermission/MemberMissionService.java @@ -0,0 +1,83 @@ +package com.soptie.server.domain.membermission; + +import java.util.Optional; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.soptie.server.api.controller.dto.request.membermission.CreateMemberMissionRequest; +import com.soptie.server.api.controller.dto.response.membermission.CreateMemberMissionResponse; +import com.soptie.server.api.controller.dto.response.membermission.GetMemberMissionResponse; +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.persistence.adapter.ChallengeAdapter; +import com.soptie.server.persistence.adapter.MemberAdapter; +import com.soptie.server.persistence.adapter.MemberMissionAdapter; +import com.soptie.server.persistence.adapter.MissionAdapter; +import com.soptie.server.persistence.adapter.ThemeAdapter; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MemberMissionService { + private final MemberMissionAdapter memberMissionAdapter; + private final ThemeAdapter themeAdapter; + private final ChallengeAdapter challengeAdapter; + private final MissionAdapter missionAdapter; + private final MemberAdapter memberAdapter; + + @Transactional + public CreateMemberMissionResponse createMemberMission(long memberId, CreateMemberMissionRequest request) { + if (memberMissionAdapter.findByMember(memberId).isPresent()) { + throw new SoftieException(ExceptionCode.BAD_REQUEST, "이미 미션을 추가한 회원"); + } + val member = memberAdapter.findById(memberId); + val mission = missionAdapter.findById(request.subRoutineId()); + val savedMemberMission = memberMissionAdapter.save(member, mission); + return CreateMemberMissionResponse.of(savedMemberMission); + } + + @Transactional + public void deleteMemberMission(long memberId, long missionId) { + val memberMission = memberMissionAdapter.findByMember(memberId) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Member ID: " + memberId)); + if (memberMission.getId() != missionId) { + throw new SoftieException( + ExceptionCode.NOT_AVAILABLE, + "Member ID: " + memberId + ", Mission ID: " + missionId); + } + memberMissionAdapter.delete(memberMission); + } + + @Transactional + public void achieveMemberMission(long memberId, long missionId) { + val member = memberAdapter.findById(memberId); + val memberMission = memberMissionAdapter.findByMember(memberId) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Member ID: " + memberId)); + if (memberMission.getId() != missionId) { + throw new SoftieException( + ExceptionCode.NOT_AVAILABLE, + "Member ID: " + memberId + ", Mission ID: " + missionId); + } + member.getCottonInfo().addRainbowCottonCount(); + memberAdapter.update(member); + memberMission.achieve(); + memberMissionAdapter.update(memberMission); + memberMissionAdapter.flush(); + memberMissionAdapter.delete(memberMission); + } + + public Optional getMemberMission(long memberId) { + return memberMissionAdapter.findByMember(memberId).map(this::toGetMemberMissionResponse); + } + + private GetMemberMissionResponse toGetMemberMissionResponse(MemberMission memberMission) { + val mission = missionAdapter.findById(memberMission.getMissionId()); + val challenge = challengeAdapter.findById(mission.getChallengeId()); + val theme = themeAdapter.findById(challenge.getThemeId()); + return GetMemberMissionResponse.of(theme, challenge, mission); + } +} diff --git a/src/main/java/com/soptie/server/domain/memberroutine/MemberRoutine.java b/src/main/java/com/soptie/server/domain/memberroutine/MemberRoutine.java new file mode 100644 index 00000000..39c0aa57 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/memberroutine/MemberRoutine.java @@ -0,0 +1,26 @@ +package com.soptie.server.domain.memberroutine; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class MemberRoutine { + private Long id; + private boolean isAchieved; + private boolean isAchievedToday; + private int achievementCount; + private long memberId; + private long routineId; + + public void achieve() { + this.isAchievedToday = true; + this.achievementCount += !this.isAchieved ? 1 : -1; + this.isAchieved = !this.isAchieved; + } + + public void initAchievement() { + this.isAchievedToday = false; + this.isAchieved = false; + } +} diff --git a/src/main/java/com/soptie/server/domain/memberroutine/MemberRoutineService.java b/src/main/java/com/soptie/server/domain/memberroutine/MemberRoutineService.java new file mode 100644 index 00000000..b8661442 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/memberroutine/MemberRoutineService.java @@ -0,0 +1,120 @@ +package com.soptie.server.domain.memberroutine; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.soptie.server.api.controller.dto.request.memberroutine.CreateMemberRoutinesRequest; +import com.soptie.server.api.controller.dto.response.memberroutine.AchieveMemberRoutineResponse; +import com.soptie.server.api.controller.dto.response.memberroutine.CreateMemberRoutinesResponse; +import com.soptie.server.api.controller.dto.response.memberroutine.GetMemberRoutinesResponse; +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.domain.routine.Routine; +import com.soptie.server.domain.theme.Theme; +import com.soptie.server.persistence.adapter.MemberAdapter; +import com.soptie.server.persistence.adapter.MemberRoutineAdapter; +import com.soptie.server.persistence.adapter.RoutineAdapter; +import com.soptie.server.persistence.adapter.ThemeAdapter; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MemberRoutineService { + private final MemberRoutineAdapter memberRoutineAdapter; + private final MemberAdapter memberAdapter; + private final RoutineAdapter routineAdapter; + private final ThemeAdapter themeAdapter; + + @Transactional + public CreateMemberRoutinesResponse createRoutines( + long memberId, + CreateMemberRoutinesRequest request + ) { + val member = memberAdapter.findById(memberId); + val routines = routineAdapter.findByIds(request.routineIds()); + val savedMemberRoutines = memberRoutineAdapter.saveAll(member, routines); + return CreateMemberRoutinesResponse.of(savedMemberRoutines); + } + + public GetMemberRoutinesResponse getMemberRoutines(long memberId) { + val memberRoutines = memberRoutineAdapter.findByMemberId(memberId); + + val routinesIds = memberRoutines.stream().map(MemberRoutine::getRoutineId).toList(); + val routines = routineAdapter.findByIds(routinesIds); + val routinesById = routines.stream().collect(Collectors.toMap(Routine::getId, routine -> routine)); + + val themeIds = routines.stream().map(Routine::getThemeId).distinct().toList(); + val themes = themeAdapter.findByIds(themeIds); + val themesById = themes.stream().collect(Collectors.toMap(Theme::getId, theme -> theme)); + + val routinesByTheme = toRoutinesByTheme(memberRoutines, routinesById, themesById); + return GetMemberRoutinesResponse.of(routinesByTheme); + } + + @Transactional + public void deleteMemberRoutines(long memberId, List memberRoutineIds) { + val memberRoutines = memberRoutineAdapter.findByIds(memberRoutineIds).stream() + .filter(memberRoutine -> memberRoutine.getMemberId() == memberId) + .toList(); + memberRoutineAdapter.deleteAll(memberRoutines); + } + + @Transactional + public AchieveMemberRoutineResponse achieveMemberRoutine(long memberId, long memberRoutineId) { + val member = memberAdapter.findById(memberId); + val memberRoutine = memberRoutineAdapter.findById(memberRoutineId); + val isAchievedToday = memberRoutine.isAchievedToday(); + + if (memberRoutine.getMemberId() != memberId) { + throw new SoftieException( + ExceptionCode.NOT_AVAILABLE, + "Member ID: " + memberId + ", MemberRoutine ID: " + memberRoutineId); + } + + if (!isAchievedToday) { + member.getCottonInfo().addBasicCottonCount(); + memberAdapter.update(member); + } + + memberRoutine.achieve(); + memberRoutineAdapter.update(memberRoutine); + + return AchieveMemberRoutineResponse.of(memberRoutine, !isAchievedToday); + } + + @Transactional + public void initAchievement() { + val memberRoutines = memberRoutineAdapter.findAchieved(); + for (val memberRoutine : memberRoutines) { + memberRoutine.initAchievement(); + } + } + + private Map> toRoutinesByTheme( + List memberRoutines, + Map routinesById, + Map themesById + ) { + return memberRoutines.stream() + .collect(Collectors.groupingBy( + // Theme-key + memberRoutine -> { + val themeId = routinesById.get(memberRoutine.getRoutineId()).getThemeId(); + return themesById.get(themeId); + }, + + // Map-value + Collectors.toMap( + memberRoutine -> routinesById.get(memberRoutine.getRoutineId()), // routine-key + memberRoutine -> memberRoutine // memberRoutine-value + ) + )); + } +} diff --git a/src/main/java/com/soptie/server/domain/routine/Routine.java b/src/main/java/com/soptie/server/domain/routine/Routine.java new file mode 100644 index 00000000..18b44401 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/routine/Routine.java @@ -0,0 +1,14 @@ +package com.soptie.server.domain.routine; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Routine { + private Long id; + @NotNull + private String content; + private long themeId; +} diff --git a/src/main/java/com/soptie/server/domain/routine/RoutineService.java b/src/main/java/com/soptie/server/domain/routine/RoutineService.java new file mode 100644 index 00000000..3e3162e2 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/routine/RoutineService.java @@ -0,0 +1,56 @@ +package com.soptie.server.domain.routine; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.soptie.server.api.controller.dto.response.routine.GetRoutinesByMemberResponse; +import com.soptie.server.api.controller.dto.response.routine.GetRoutinesByThemeResponse; +import com.soptie.server.domain.memberroutine.MemberRoutine; +import com.soptie.server.persistence.adapter.MemberRoutineAdapter; +import com.soptie.server.persistence.adapter.RoutineAdapter; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class RoutineService { + private final RoutineAdapter routineAdapter; + private final MemberRoutineAdapter memberRoutineAdapter; + + public GetRoutinesByThemeResponse getRoutinesByThemeIds(Set themeIds) { + val routinesByThemeId = new LinkedHashMap>(); + for (val themeId : themeIds) { + val routines = routineAdapter.findByThemeId(themeId); + routinesByThemeId.put(themeId, routines); + } + return GetRoutinesByThemeResponse.of(routinesByThemeId); + } + + public GetRoutinesByMemberResponse getRoutinesByThemeId(long memberId, long themeId) { + val routines = routineAdapter.findByThemeId(themeId); + val memberRoutineIds = memberRoutineAdapter.findByMemberId(memberId).stream() + .map(MemberRoutine::getRoutineId) + .toList(); + return GetRoutinesByMemberResponse.of(getRoutineToMember(routines, memberRoutineIds)); + } + + private Map> getRoutineToMember(List routines, List memberRoutineIds) { + val routineToMember = new HashMap>(); + routineToMember.put(true, new ArrayList<>()); + routineToMember.put(false, new ArrayList<>()); + for (val routine : routines) { + val isMemberRoutine = memberRoutineIds.contains(routine.getId()); + routineToMember.get(isMemberRoutine).add(routine); + } + return routineToMember; + } +} diff --git a/src/main/java/com/soptie/server/domain/theme/Theme.java b/src/main/java/com/soptie/server/domain/theme/Theme.java new file mode 100644 index 00000000..1b8c0490 --- /dev/null +++ b/src/main/java/com/soptie/server/domain/theme/Theme.java @@ -0,0 +1,19 @@ +package com.soptie.server.domain.theme; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Theme { + private Long id; + @NotNull + private String name; + @NotNull + private String comment; + @NotNull + private String description; + private int sequence; + private Long makerId; +} diff --git a/src/main/java/com/soptie/server/domain/theme/ThemeService.java b/src/main/java/com/soptie/server/domain/theme/ThemeService.java new file mode 100644 index 00000000..a278693d --- /dev/null +++ b/src/main/java/com/soptie/server/domain/theme/ThemeService.java @@ -0,0 +1,26 @@ +package com.soptie.server.domain.theme; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.soptie.server.api.controller.dto.response.theme.GetThemesResponse; +import com.soptie.server.persistence.adapter.ThemeAdapter; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class ThemeService { + private final ThemeAdapter themeAdapter; + + public GetThemesResponse getBasicThemes() { + val themes = themeAdapter.findByBasic(); + return GetThemesResponse.of(themes); + } + + public Theme acquireById(long themeId) { + return themeAdapter.findById(themeId); + } +} diff --git a/src/main/java/com/soptie/server/version/service/VersionServiceImpl.java b/src/main/java/com/soptie/server/domain/version/VersionService.java similarity index 56% rename from src/main/java/com/soptie/server/version/service/VersionServiceImpl.java rename to src/main/java/com/soptie/server/domain/version/VersionService.java index 0f4ace27..47a1b1a2 100644 --- a/src/main/java/com/soptie/server/version/service/VersionServiceImpl.java +++ b/src/main/java/com/soptie/server/domain/version/VersionService.java @@ -1,21 +1,20 @@ -package com.soptie.server.version.service; +package com.soptie.server.domain.version; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import com.soptie.server.common.config.ValueConfig; -import com.soptie.server.version.service.dto.response.AppVersionGetServiceResponse; +import com.soptie.server.api.controller.dto.response.version.GetAppVersionResponse; +import com.soptie.server.common.support.ValueConfig; import lombok.RequiredArgsConstructor; @Service @RequiredArgsConstructor @Transactional(readOnly = true) -public class VersionServiceImpl implements VersionService { +public class VersionService { - @Override - public AppVersionGetServiceResponse getClientAppVersion() { - return AppVersionGetServiceResponse.of( + public GetAppVersionResponse getClientAppVersion() { + return GetAppVersionResponse.of( ValueConfig.IOS_APP_VERSION, ValueConfig.IOS_FORCE_UPDATE_VERSION, ValueConfig.ANDROID_APP_VERSION, diff --git a/src/main/java/com/soptie/server/common/config/RestTemplateConfig.java b/src/main/java/com/soptie/server/external/config/RestTemplateConfig.java similarity index 87% rename from src/main/java/com/soptie/server/common/config/RestTemplateConfig.java rename to src/main/java/com/soptie/server/external/config/RestTemplateConfig.java index e7d768ef..d5ecaeb2 100644 --- a/src/main/java/com/soptie/server/common/config/RestTemplateConfig.java +++ b/src/main/java/com/soptie/server/external/config/RestTemplateConfig.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.config; +package com.soptie.server.external.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/soptie/server/auth/service/AppleService.java b/src/main/java/com/soptie/server/external/oauth/AppleService.java similarity index 66% rename from src/main/java/com/soptie/server/auth/service/AppleService.java rename to src/main/java/com/soptie/server/external/oauth/AppleService.java index 88df2699..31c93889 100644 --- a/src/main/java/com/soptie/server/auth/service/AppleService.java +++ b/src/main/java/com/soptie/server/external/oauth/AppleService.java @@ -1,4 +1,4 @@ -package com.soptie.server.auth.service; +package com.soptie.server.external.oauth; public interface AppleService { diff --git a/src/main/java/com/soptie/server/auth/service/AppleServiceImpl.java b/src/main/java/com/soptie/server/external/oauth/AppleServiceImpl.java similarity index 93% rename from src/main/java/com/soptie/server/auth/service/AppleServiceImpl.java rename to src/main/java/com/soptie/server/external/oauth/AppleServiceImpl.java index 5f540bb5..1c37464c 100644 --- a/src/main/java/com/soptie/server/auth/service/AppleServiceImpl.java +++ b/src/main/java/com/soptie/server/external/oauth/AppleServiceImpl.java @@ -1,6 +1,4 @@ -package com.soptie.server.auth.service; - -import static com.soptie.server.auth.message.ErrorCode.*; +package com.soptie.server.external.oauth; import java.io.BufferedReader; import java.io.IOException; @@ -25,8 +23,9 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import com.soptie.server.auth.exception.AuthException; -import com.soptie.server.common.config.ValueConfig; +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.ValueConfig; import io.jsonwebtoken.Jwts; import lombok.RequiredArgsConstructor; @@ -106,7 +105,7 @@ private PublicKey makePublicKey(String accessToken, JsonArray publicKeyList) { val matchingPublicKey = findMatchingPublicKey(publicKeyList, kid, alg); if (Objects.isNull(matchingPublicKey)) { - throw new AuthException(INVALID_KEY); + throw new SoftieException(ExceptionCode.UNAUTHORIZED); } return getPublicKey(matchingPublicKey); @@ -148,7 +147,7 @@ private PublicKey getPublicKey(JsonObject object) { return keyFactory.generatePublic(publicKeySpec); } catch (InvalidKeySpecException | NoSuchAlgorithmException exception) { - throw new AuthException(INVALID_KEY); + throw new SoftieException(ExceptionCode.UNAUTHORIZED); } } } diff --git a/src/main/java/com/soptie/server/auth/service/KakaoService.java b/src/main/java/com/soptie/server/external/oauth/KakaoService.java similarity index 66% rename from src/main/java/com/soptie/server/auth/service/KakaoService.java rename to src/main/java/com/soptie/server/external/oauth/KakaoService.java index 7d9dff72..10adf522 100644 --- a/src/main/java/com/soptie/server/auth/service/KakaoService.java +++ b/src/main/java/com/soptie/server/external/oauth/KakaoService.java @@ -1,4 +1,4 @@ -package com.soptie.server.auth.service; +package com.soptie.server.external.oauth; public interface KakaoService { diff --git a/src/main/java/com/soptie/server/auth/service/KakaoServiceImpl.java b/src/main/java/com/soptie/server/external/oauth/KakaoServiceImpl.java similarity index 79% rename from src/main/java/com/soptie/server/auth/service/KakaoServiceImpl.java rename to src/main/java/com/soptie/server/external/oauth/KakaoServiceImpl.java index 6dd3e971..652abe59 100644 --- a/src/main/java/com/soptie/server/auth/service/KakaoServiceImpl.java +++ b/src/main/java/com/soptie/server/external/oauth/KakaoServiceImpl.java @@ -1,6 +1,4 @@ -package com.soptie.server.auth.service; - -import static com.soptie.server.auth.message.ErrorCode.*; +package com.soptie.server.external.oauth; import java.util.Map; @@ -11,8 +9,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.JsonArray; -import com.soptie.server.auth.exception.AuthException; -import com.soptie.server.common.config.ValueConfig; +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.ValueConfig; import lombok.RequiredArgsConstructor; import lombok.val; @@ -34,7 +33,7 @@ public String getKakaoData(String socialAccessToken) { val responseData = restTemplate.postForEntity(valueConfig.getKakaoUri(), httpEntity, Object.class); return objectMapper.convertValue(responseData.getBody(), Map.class).get("id").toString(); } catch (Exception exception) { - throw new AuthException(INVALID_TOKEN); + throw new SoftieException(ExceptionCode.UNAUTHORIZED); } } } diff --git a/src/main/java/com/soptie/server/maker/adapter/MakerFinder.java b/src/main/java/com/soptie/server/maker/adapter/MakerFinder.java deleted file mode 100644 index f628ea10..00000000 --- a/src/main/java/com/soptie/server/maker/adapter/MakerFinder.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.soptie.server.maker.adapter; - -import java.util.List; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.maker.repository.MakerRepository; -import com.soptie.server.maker.repository.dto.MakerThemeResponse; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class MakerFinder { - - private final MakerRepository makerRepository; - - public List findAllWithTheme() { - return makerRepository.findAllWithTheme(); - } -} diff --git a/src/main/java/com/soptie/server/maker/controller/MakerController.java b/src/main/java/com/soptie/server/maker/controller/MakerController.java deleted file mode 100644 index 25b5e56f..00000000 --- a/src/main/java/com/soptie/server/maker/controller/MakerController.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.soptie.server.maker.controller; - -import static com.soptie.server.common.dto.SuccessResponse.success; -import static com.soptie.server.maker.message.MakerSuccessMessage.SUCCESS_GET_MAKER_THEME; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.maker.controller.docs.MakerControllerDocs; -import com.soptie.server.maker.controller.dto.response.MakerListAcquireResponse; -import com.soptie.server.maker.service.MakerService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v2/makers") -public class MakerController implements MakerControllerDocs { - - private final MakerService makerService; - - @Override - @GetMapping - @ResponseStatus(HttpStatus.OK) - public SuccessResponse acquireAll() { - val response = makerService.acquireAll(); - return success(SUCCESS_GET_MAKER_THEME.getMessage(), MakerListAcquireResponse.from(response)); - } -} diff --git a/src/main/java/com/soptie/server/maker/controller/dto/response/MakerListAcquireResponse.java b/src/main/java/com/soptie/server/maker/controller/dto/response/MakerListAcquireResponse.java deleted file mode 100644 index 0987387a..00000000 --- a/src/main/java/com/soptie/server/maker/controller/dto/response/MakerListAcquireResponse.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.soptie.server.maker.controller.dto.response; - -import static lombok.AccessLevel.PRIVATE; - -import java.util.List; - -import com.soptie.server.maker.service.dto.MakerListAcquireServiceResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MakerListAcquireResponse( - List makers -) { - - public static MakerListAcquireResponse from(MakerListAcquireServiceResponse response) { - return MakerListAcquireResponse.builder() - .makers(response.makers().stream().map(MakerAcquireResponse::from).toList()) - .build(); - } - - @Builder(access = PRIVATE) - private record MakerAcquireResponse( - long makerId, - @NonNull String content, - @NonNull String name, - @NonNull String profileImageUrl, - @NonNull List tags, - long themeId, - @NonNull String description, - @NonNull String themeName, - @NonNull String modifier - ) { - - public static MakerAcquireResponse from(MakerListAcquireServiceResponse.MakerAcquireServiceResponse maker) { - return MakerAcquireResponse.builder() - .makerId(maker.makerId()) - .content(maker.content()) - .name(maker.name()) - .profileImageUrl(maker.profileImageUrl()) - .tags(maker.tags()) - .themeId(maker.themeId()) - .description(maker.description()) - .themeName(maker.themeName()) - .modifier(maker.modifier()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/maker/entity/Maker.java b/src/main/java/com/soptie/server/maker/entity/Maker.java deleted file mode 100644 index 26fe10bc..00000000 --- a/src/main/java/com/soptie/server/maker/entity/Maker.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.soptie.server.maker.entity; - -import static jakarta.persistence.GenerationType.IDENTITY; -import static lombok.AccessLevel.PROTECTED; - -import java.util.List; - -import com.soptie.server.common.support.StringListConverter; - -import jakarta.persistence.Column; -import jakarta.persistence.Convert; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Getter -@NoArgsConstructor(access = PROTECTED) -@AllArgsConstructor -public class Maker { - - @Id - @GeneratedValue(strategy = IDENTITY) - @Column(name = "maker_id") - private Long id; - - @Column(nullable = false) - private String name; - - private String job; - - private String profileImageUrl; - - private String content; - - @Column(nullable = false) - private long themeId; - - @Convert(converter = StringListConverter.class) - private List tags; -} diff --git a/src/main/java/com/soptie/server/maker/exception/MakerException.java b/src/main/java/com/soptie/server/maker/exception/MakerException.java deleted file mode 100644 index a29084e9..00000000 --- a/src/main/java/com/soptie/server/maker/exception/MakerException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.maker.exception; - -import com.soptie.server.doll.message.ErrorCode; - -import lombok.Getter; - -@Getter -public class MakerException extends RuntimeException { - - private final ErrorCode errorCode; - - public MakerException(ErrorCode errorCode) { - super("[MakerException] : " + errorCode.getMessage()); - this.errorCode = errorCode; - } -} diff --git a/src/main/java/com/soptie/server/maker/message/MakerErrorCode.java b/src/main/java/com/soptie/server/maker/message/MakerErrorCode.java deleted file mode 100644 index 3fedcea4..00000000 --- a/src/main/java/com/soptie/server/maker/message/MakerErrorCode.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.maker.message; - -import static org.springframework.http.HttpStatus.NOT_FOUND; - -import org.springframework.http.HttpStatus; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum MakerErrorCode { - - /* 404 NOT_FOUND : 자원을 찾을 수 없음 */ - INVALID_MAKER(NOT_FOUND, "유효하지 않은 메이커입니다."); - - private final HttpStatus httpStatus; - private final String message; -} diff --git a/src/main/java/com/soptie/server/maker/message/MakerSuccessMessage.java b/src/main/java/com/soptie/server/maker/message/MakerSuccessMessage.java deleted file mode 100644 index 6df4f767..00000000 --- a/src/main/java/com/soptie/server/maker/message/MakerSuccessMessage.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soptie.server.maker.message; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum MakerSuccessMessage { - - SUCCESS_GET_MAKER_THEME("메이커 테마 조회 성공"); - - private final String message; -} diff --git a/src/main/java/com/soptie/server/maker/repository/MakerCustomRepository.java b/src/main/java/com/soptie/server/maker/repository/MakerCustomRepository.java deleted file mode 100644 index 2fab4b80..00000000 --- a/src/main/java/com/soptie/server/maker/repository/MakerCustomRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.soptie.server.maker.repository; - -import java.util.List; - -import com.soptie.server.maker.repository.dto.MakerThemeResponse; - -public interface MakerCustomRepository { - List findAllWithTheme(); -} diff --git a/src/main/java/com/soptie/server/maker/repository/MakerRepository.java b/src/main/java/com/soptie/server/maker/repository/MakerRepository.java deleted file mode 100644 index 98d2415c..00000000 --- a/src/main/java/com/soptie/server/maker/repository/MakerRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soptie.server.maker.repository; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.maker.entity.Maker; - -public interface MakerRepository extends JpaRepository, MakerCustomRepository { -} diff --git a/src/main/java/com/soptie/server/maker/repository/MakerRepositoryImpl.java b/src/main/java/com/soptie/server/maker/repository/MakerRepositoryImpl.java deleted file mode 100644 index e9f36125..00000000 --- a/src/main/java/com/soptie/server/maker/repository/MakerRepositoryImpl.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.soptie.server.maker.repository; - -import static com.soptie.server.maker.entity.QMaker.maker; -import static com.soptie.server.theme.entity.QTheme.theme; - -import java.util.List; - -import org.springframework.stereotype.Repository; - -import com.querydsl.jpa.impl.JPAQueryFactory; -import com.soptie.server.maker.repository.dto.MakerThemeResponse; -import com.soptie.server.maker.repository.dto.QMakerThemeResponse; - -import lombok.RequiredArgsConstructor; - -@Repository -@RequiredArgsConstructor -public class MakerRepositoryImpl implements MakerCustomRepository { - - private final JPAQueryFactory queryFactory; - - @Override - public List findAllWithTheme() { - return queryFactory.select(new QMakerThemeResponse(maker, theme)) - .from(maker) - .leftJoin(theme).on(maker.themeId.eq(theme.id)) - .fetchJoin() - .fetch(); - } -} diff --git a/src/main/java/com/soptie/server/maker/repository/dto/MakerThemeResponse.java b/src/main/java/com/soptie/server/maker/repository/dto/MakerThemeResponse.java deleted file mode 100644 index 8131796e..00000000 --- a/src/main/java/com/soptie/server/maker/repository/dto/MakerThemeResponse.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.soptie.server.maker.repository.dto; - -import java.util.List; - -import com.querydsl.core.annotations.QueryProjection; -import com.soptie.server.maker.entity.Maker; -import com.soptie.server.theme.entity.Theme; - -import lombok.NonNull; - -public record MakerThemeResponse( - long makerId, - @NonNull String content, - @NonNull String name, - @NonNull String profileImageUrl, - @NonNull List tags, - long themeId, - @NonNull String description, - @NonNull String themeName, - @NonNull String modifier -) { - - @QueryProjection - public MakerThemeResponse(Maker maker, Theme theme) { - this( - maker.getId(), - maker.getContent(), - maker.getName(), - maker.getProfileImageUrl(), - maker.getTags(), - theme.getId(), - theme.getDescription(), - theme.getName(), - theme.getModifier() - ); - } -} diff --git a/src/main/java/com/soptie/server/maker/service/MakerService.java b/src/main/java/com/soptie/server/maker/service/MakerService.java deleted file mode 100644 index 0ed0dc9b..00000000 --- a/src/main/java/com/soptie/server/maker/service/MakerService.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.soptie.server.maker.service; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.maker.adapter.MakerFinder; -import com.soptie.server.maker.service.dto.MakerListAcquireServiceResponse; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class MakerService { - - private final MakerFinder makerFinder; - - public MakerListAcquireServiceResponse acquireAll() { - val makers = makerFinder.findAllWithTheme(); - return MakerListAcquireServiceResponse.from(makers); - } -} diff --git a/src/main/java/com/soptie/server/maker/service/dto/MakerListAcquireServiceResponse.java b/src/main/java/com/soptie/server/maker/service/dto/MakerListAcquireServiceResponse.java deleted file mode 100644 index 0ffb6c35..00000000 --- a/src/main/java/com/soptie/server/maker/service/dto/MakerListAcquireServiceResponse.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.soptie.server.maker.service.dto; - -import static lombok.AccessLevel.PRIVATE; - -import java.util.List; - -import com.soptie.server.maker.repository.dto.MakerThemeResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MakerListAcquireServiceResponse( - List makers -) { - - public static MakerListAcquireServiceResponse from(List makers) { - return MakerListAcquireServiceResponse.builder() - .makers(makers.stream().map(MakerAcquireServiceResponse::from).toList()) - .build(); - } - - @Builder(access = PRIVATE) - public record MakerAcquireServiceResponse( - long makerId, - @NonNull String content, - @NonNull String name, - @NonNull String profileImageUrl, - @NonNull List tags, - long themeId, - @NonNull String description, - @NonNull String themeName, - @NonNull String modifier - ) { - - public static MakerAcquireServiceResponse from(MakerThemeResponse maker) { - return MakerAcquireServiceResponse.builder() - .makerId(maker.makerId()) - .content(maker.content()) - .name(maker.name()) - .profileImageUrl(maker.profileImageUrl()) - .tags(maker.tags()) - .themeId(maker.themeId()) - .description(maker.description()) - .themeName(maker.themeName()) - .modifier(maker.modifier()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/member/adapter/MemberDeleter.java b/src/main/java/com/soptie/server/member/adapter/MemberDeleter.java deleted file mode 100644 index 393ccc3a..00000000 --- a/src/main/java/com/soptie/server/member/adapter/MemberDeleter.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.soptie.server.member.adapter; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.repository.MemberRepository; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class MemberDeleter { - - private final MemberRepository memberRepository; - - public void delete(Member member) { - memberRepository.delete(member); - } -} diff --git a/src/main/java/com/soptie/server/member/adapter/MemberFinder.java b/src/main/java/com/soptie/server/member/adapter/MemberFinder.java deleted file mode 100644 index dcfe7394..00000000 --- a/src/main/java/com/soptie/server/member/adapter/MemberFinder.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.soptie.server.member.adapter; - -import static com.soptie.server.member.message.ErrorCode.*; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.exception.MemberException; -import com.soptie.server.member.repository.MemberRepository; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class MemberFinder { - - private final MemberRepository memberRepository; - - public Member findById(long id) { - return memberRepository.findById(id) - .orElseThrow(() -> new MemberException(INVALID_MEMBER)); - } -} diff --git a/src/main/java/com/soptie/server/member/controller/MemberController.java b/src/main/java/com/soptie/server/member/controller/MemberController.java deleted file mode 100644 index ce57aef0..00000000 --- a/src/main/java/com/soptie/server/member/controller/MemberController.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.soptie.server.member.controller; - -import static com.soptie.server.common.dto.SuccessResponse.*; -import static com.soptie.server.common.support.UriGenerator.*; -import static com.soptie.server.member.message.MemberSuccessMessage.*; - -import java.security.Principal; - -import org.springframework.http.ResponseEntity; -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.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.BaseResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.member.controller.docs.MemberControllerDocs; -import com.soptie.server.member.controller.dto.request.MemberProfileCreateRequest; -import com.soptie.server.member.controller.dto.response.MemberCottonCountGetResponse; -import com.soptie.server.member.controller.dto.response.MemberHomeInfoGetResponse; -import com.soptie.server.member.entity.CottonType; -import com.soptie.server.member.service.MemberService; -import com.soptie.server.member.service.dto.request.CottonGiveServiceRequest; -import com.soptie.server.member.service.dto.request.MemberHomeInfoGetServiceRequest; -import com.soptie.server.member.service.dto.request.MemberProfileCreateServiceRequest; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("api/v1/members") -public class MemberController implements MemberControllerDocs { - - private final MemberService memberService; - - @PostMapping - public ResponseEntity createMemberProfile( - Principal principal, - @RequestBody MemberProfileCreateRequest request - ) { - val memberId = Long.parseLong(principal.getName()); - memberService.createMemberProfile(MemberProfileCreateServiceRequest.of(memberId, request)); - return ResponseEntity.created(getUri("/")).body(success(SUCCESS_CREATE_PROFILE.getMessage())); - } - - @PatchMapping("/cotton/{cottonType}") - public ResponseEntity> giveCotton( - Principal principal, - @PathVariable CottonType cottonType - ) { - val memberId = Long.parseLong(principal.getName()); - val response = MemberCottonCountGetResponse.of( - memberService.giveCotton(CottonGiveServiceRequest.of(memberId, cottonType))); - return ResponseEntity.ok(success(SUCCESS_GIVE_COTTON.getMessage(), response)); - } - - @GetMapping - public ResponseEntity> getMemberHomeInfo(Principal principal) { - val memberId = Long.parseLong(principal.getName()); - val response = MemberHomeInfoGetResponse.of( - memberService.getMemberHomeInfo(MemberHomeInfoGetServiceRequest.of(memberId))); - return ResponseEntity.ok(success(SUCCESS_HOME_INFO.getMessage(), response)); - } -} diff --git a/src/main/java/com/soptie/server/member/controller/dto/request/MemberProfileCreateRequest.java b/src/main/java/com/soptie/server/member/controller/dto/request/MemberProfileCreateRequest.java deleted file mode 100644 index 1a3a2793..00000000 --- a/src/main/java/com/soptie/server/member/controller/dto/request/MemberProfileCreateRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.soptie.server.member.controller.dto.request; - -import java.util.List; - -import com.soptie.server.doll.entity.DollType; - -import lombok.NonNull; - -public record MemberProfileCreateRequest( - @NonNull DollType dollType, - @NonNull String name, - @NonNull List routines -) { -} diff --git a/src/main/java/com/soptie/server/member/controller/dto/response/MemberCottonCountGetResponse.java b/src/main/java/com/soptie/server/member/controller/dto/response/MemberCottonCountGetResponse.java deleted file mode 100644 index d4dfe18e..00000000 --- a/src/main/java/com/soptie/server/member/controller/dto/response/MemberCottonCountGetResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.member.controller.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.member.service.dto.response.MemberCottonCountGetServiceResponse; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberCottonCountGetResponse( - int cottonCount -) { - - public static MemberCottonCountGetResponse of(MemberCottonCountGetServiceResponse response) { - return MemberCottonCountGetResponse.builder() - .cottonCount(response.cottonCount()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/member/controller/dto/response/MemberHomeInfoGetResponse.java b/src/main/java/com/soptie/server/member/controller/dto/response/MemberHomeInfoGetResponse.java deleted file mode 100644 index 19166a68..00000000 --- a/src/main/java/com/soptie/server/member/controller/dto/response/MemberHomeInfoGetResponse.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.soptie.server.member.controller.dto.response; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.member.service.dto.response.MemberHomeInfoGetServiceResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberHomeInfoGetResponse( - @NonNull String name, - @NonNull DollType dollType, - @NonNull String frameImageUrl, - int dailyCottonCount, - int happinessCottonCount, - @NonNull List conversations -) { - - public static MemberHomeInfoGetResponse of(MemberHomeInfoGetServiceResponse response) { - return MemberHomeInfoGetResponse.builder() - .name(response.name()) - .dollType(response.dollType()) - .frameImageUrl(response.frameImageUrl()) - .dailyCottonCount(response.dailyCottonCount()) - .happinessCottonCount(response.happinessCottonCount()) - .conversations(response.conversations()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/member/entity/Cotton.java b/src/main/java/com/soptie/server/member/entity/Cotton.java deleted file mode 100644 index cf2d0a1a..00000000 --- a/src/main/java/com/soptie/server/member/entity/Cotton.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.soptie.server.member.entity; - -import static com.soptie.server.common.config.ValueConfig.*; -import static com.soptie.server.member.message.ErrorCode.*; -import static lombok.AccessLevel.*; - -import com.soptie.server.member.exception.MemberException; -import com.soptie.server.memberdoll.entity.MemberDoll; - -import jakarta.persistence.Embeddable; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Embeddable -@NoArgsConstructor -@AllArgsConstructor(access = PACKAGE) -@Getter -public class Cotton { - - private int dailyCottonCount; - private int happinessCottonCount; - - protected void addDailyCotton() { - this.dailyCottonCount++; - } - - protected void addHappinessCotton() { - this.happinessCottonCount++; - } - - protected int subtractAndGetCotton(CottonType type, MemberDoll memberDoll) { - return switch (type) { - case DAILY -> subtractAndGetDailyCotton(); - case HAPPINESS -> subtractAndGetHappinessCotton(memberDoll); - }; - } - - private int subtractAndGetDailyCotton() { - checkCount(this.dailyCottonCount); - this.dailyCottonCount--; - return this.dailyCottonCount; - } - - private int subtractAndGetHappinessCotton(MemberDoll memberDoll) { - checkCount(this.happinessCottonCount); - this.happinessCottonCount--; - memberDoll.addHappinessCottonCount(); - return this.happinessCottonCount; - } - - private void checkCount(int count) { - if (count <= MIN_COTTON_COUNT) { - throw new MemberException(NOT_ENOUGH_COTTON); - } - } -} diff --git a/src/main/java/com/soptie/server/member/entity/Member.java b/src/main/java/com/soptie/server/member/entity/Member.java deleted file mode 100644 index d4223005..00000000 --- a/src/main/java/com/soptie/server/member/entity/Member.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.soptie.server.member.entity; - -import static com.soptie.server.member.message.ErrorCode.*; -import static jakarta.persistence.EnumType.*; -import static jakarta.persistence.GenerationType.*; - -import java.util.Objects; - -import com.soptie.server.common.entity.BaseTime; -import com.soptie.server.member.exception.MemberException; -import com.soptie.server.memberdoll.entity.MemberDoll; -import com.soptie.server.routine.entity.RoutineType; - -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.OneToOne; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -@Getter -public class Member extends BaseTime { - - @Id - @GeneratedValue(strategy = IDENTITY) - @Column(name = "member_id") - private Long id; - - @Enumerated(value = STRING) - private SocialType socialType; - private String socialId; - - private String refreshToken; - - @Embedded - private Cotton cottonInfo; - - @OneToOne - @JoinColumn(name = "doll_id") - private MemberDoll memberDoll; - - @Builder - public Member(SocialType socialType, String socialId) { - this.socialType = socialType; - this.socialId = socialId; - this.cottonInfo = new Cotton(0, 0); - } - - public Member(Long id, MemberDoll memberDoll, int dailyCottonCount) { - this.id = id; - this.cottonInfo = new Cotton(dailyCottonCount, 0); - this.memberDoll = memberDoll; - } - - public Member(Long id) { - this.id = id; - } - - public void registerMemberDoll(MemberDoll memberDoll) { - this.memberDoll = memberDoll; - } - - public void updateRefreshToken(String refreshToken) { - this.refreshToken = refreshToken; - } - - public void resetRefreshToken() { - this.refreshToken = null; - } - - public void addCottonCount(RoutineType type) { - switch (type) { - case DAILY -> this.cottonInfo.addDailyCotton(); - case CHALLENGE -> this.cottonInfo.addHappinessCotton(); - } - } - - public int subtractAndGetCotton(CottonType type) { - if (Objects.isNull(this.memberDoll)) { - throw new MemberException(NOT_EXIST_DOLL); - } - return cottonInfo.subtractAndGetCotton(type, this.memberDoll); - } - - public void checkMemberDollExist() { - if (!isMemberDollExist()) { - throw new MemberException(NOT_EXIST_DOLL); - } - } - - public void checkMemberDollNonExist() { - if (isMemberDollExist()) { - throw new MemberException(EXIST_PROFILE); - } - } - - public boolean isMemberDollExist() { - return Objects.nonNull(this.getMemberDoll()); - } -} diff --git a/src/main/java/com/soptie/server/member/exception/MemberException.java b/src/main/java/com/soptie/server/member/exception/MemberException.java deleted file mode 100644 index 4d10ee9d..00000000 --- a/src/main/java/com/soptie/server/member/exception/MemberException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.member.exception; - -import com.soptie.server.member.message.ErrorCode; - -import lombok.Getter; - -@Getter -public class MemberException extends RuntimeException { - - private final ErrorCode errorCode; - - public MemberException(ErrorCode errorCode) { - super("[MemberException] : " + errorCode.getMessage()); - this.errorCode = errorCode; - } -} diff --git a/src/main/java/com/soptie/server/member/message/ErrorCode.java b/src/main/java/com/soptie/server/member/message/ErrorCode.java deleted file mode 100644 index 0a55842b..00000000 --- a/src/main/java/com/soptie/server/member/message/ErrorCode.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.soptie.server.member.message; - -import static org.springframework.http.HttpStatus.*; - -import org.springframework.http.HttpStatus; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public enum ErrorCode { - - /* 400 BAD_REQUEST : 잘못된 요청 */ - INACCESSIBLE_ROUTINE(BAD_REQUEST, "회원의 루틴이 아닙니다."), - NOT_ENOUGH_COTTON(BAD_REQUEST, "솜뭉치가 부족합니다."), - - /* 404 NOT_FOUND : 자원을 찾을 수 없음 */ - INVALID_MEMBER(NOT_FOUND, "유효하지 않은 회원입니다."), - NOT_EXIST_DOLL(NOT_FOUND, "인형을 가지고 있지 않은 회원입니다."), - - /* 409 CONFLICT : 중복된 데이터 존재 */ - EXIST_PROFILE(CONFLICT, "프로필이 이미 존재합니다."); - - private final HttpStatus httpStatus; - private final String message; -} diff --git a/src/main/java/com/soptie/server/member/message/MemberSuccessMessage.java b/src/main/java/com/soptie/server/member/message/MemberSuccessMessage.java deleted file mode 100644 index e6d69794..00000000 --- a/src/main/java/com/soptie/server/member/message/MemberSuccessMessage.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soptie.server.member.message; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum MemberSuccessMessage { - - SUCCESS_CREATE_PROFILE("프로필 생성 성공"), - SUCCESS_GIVE_COTTON("솜뭉치 주기 성공"), - SUCCESS_HOME_INFO("홈 화면 불러오기 성공"); - - private final String message; -} diff --git a/src/main/java/com/soptie/server/member/repository/MemberRepository.java b/src/main/java/com/soptie/server/member/repository/MemberRepository.java deleted file mode 100644 index 048018aa..00000000 --- a/src/main/java/com/soptie/server/member/repository/MemberRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.soptie.server.member.repository; - -import java.util.Optional; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.entity.SocialType; - -public interface MemberRepository extends JpaRepository { - Optional findBySocialTypeAndSocialId(SocialType socialType, String socialId); - - Optional findByRefreshToken(String refreshToken); -} diff --git a/src/main/java/com/soptie/server/member/service/MemberService.java b/src/main/java/com/soptie/server/member/service/MemberService.java deleted file mode 100644 index 3f47138f..00000000 --- a/src/main/java/com/soptie/server/member/service/MemberService.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.member.service; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.service.dto.request.CottonGiveServiceRequest; -import com.soptie.server.member.service.dto.request.MemberHomeInfoGetServiceRequest; -import com.soptie.server.member.service.dto.request.MemberProfileCreateServiceRequest; -import com.soptie.server.member.service.dto.response.MemberCottonCountGetServiceResponse; -import com.soptie.server.member.service.dto.response.MemberHomeInfoGetServiceResponse; - -public interface MemberService { - - void createMemberProfile(MemberProfileCreateServiceRequest request); - - MemberCottonCountGetServiceResponse giveCotton(CottonGiveServiceRequest request); - - MemberHomeInfoGetServiceResponse getMemberHomeInfo(MemberHomeInfoGetServiceRequest request); - - void deleteMember(Member member); -} diff --git a/src/main/java/com/soptie/server/member/service/MemberServiceImpl.java b/src/main/java/com/soptie/server/member/service/MemberServiceImpl.java deleted file mode 100644 index d94821ae..00000000 --- a/src/main/java/com/soptie/server/member/service/MemberServiceImpl.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.soptie.server.member.service; - -import java.util.List; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.conversation.adapter.ConversationFinder; -import com.soptie.server.conversation.entity.Conversation; -import com.soptie.server.doll.adapter.DollFinder; -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.member.adapter.MemberDeleter; -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.service.dto.request.CottonGiveServiceRequest; -import com.soptie.server.member.service.dto.request.MemberHomeInfoGetServiceRequest; -import com.soptie.server.member.service.dto.request.MemberProfileCreateServiceRequest; -import com.soptie.server.member.service.dto.response.MemberCottonCountGetServiceResponse; -import com.soptie.server.member.service.dto.response.MemberHomeInfoGetServiceResponse; -import com.soptie.server.memberdoll.adapter.MemberDollSaver; -import com.soptie.server.memberdoll.entity.MemberDoll; -import com.soptie.server.memberroutine.adapter.MemberRoutineSaver; -import com.soptie.server.routine.adapter.RoutineFinder; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class MemberServiceImpl implements MemberService { - - private final ConversationFinder conversationFinder; - private final MemberFinder memberFinder; - private final MemberDeleter memberDeleter; - private final DollFinder dollFinder; - private final RoutineFinder routineFinder; - private final MemberDollSaver memberDollSaver; - private final MemberRoutineSaver memberRoutineSaver; - - @Override - @Transactional - public void createMemberProfile(MemberProfileCreateServiceRequest request) { - val member = memberFinder.findById(request.memberId()); - member.checkMemberDollNonExist(); - createDailyRoutines(member, request.routines()); - createMemberDoll(member, request.dollType(), request.name()); - } - - @Override - @Transactional - public MemberCottonCountGetServiceResponse giveCotton(CottonGiveServiceRequest request) { - val member = memberFinder.findById(request.memberId()); - val cottonCount = member.subtractAndGetCotton(request.cottonType()); - return MemberCottonCountGetServiceResponse.of(cottonCount); - } - - @Override - public MemberHomeInfoGetServiceResponse getMemberHomeInfo(MemberHomeInfoGetServiceRequest request) { - val member = memberFinder.findById(request.memberId()); - member.checkMemberDollExist(); - val conversations = getConversations(); - return MemberHomeInfoGetServiceResponse.of(member, conversations); - } - - @Override - public void deleteMember(Member member) { - memberDeleter.delete(member); - } - - private void createDailyRoutines(Member member, List routineIds) { - routineIds.forEach(id -> { - val routine = routineFinder.findById(id); - memberRoutineSaver.checkHasDeletedAndSave(member, routine); - }); - } - - private void createMemberDoll(Member member, DollType dollType, String name) { - val doll = dollFinder.findByType(dollType); - val memberDoll = new MemberDoll(member, doll, name); - memberDollSaver.save(memberDoll); - } - - private List getConversations() { - return conversationFinder.findAll().stream().map(Conversation::getContent).toList(); - } -} diff --git a/src/main/java/com/soptie/server/member/service/dto/request/CottonGiveServiceRequest.java b/src/main/java/com/soptie/server/member/service/dto/request/CottonGiveServiceRequest.java deleted file mode 100644 index 8bb7c4d4..00000000 --- a/src/main/java/com/soptie/server/member/service/dto/request/CottonGiveServiceRequest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.soptie.server.member.service.dto.request; - -import static lombok.AccessLevel.*; - -import com.soptie.server.member.entity.CottonType; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record CottonGiveServiceRequest( - long memberId, - @NonNull CottonType cottonType -) { - - public static CottonGiveServiceRequest of(long memberId, CottonType cottonType) { - return CottonGiveServiceRequest.builder() - .memberId(memberId) - .cottonType(cottonType) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/member/service/dto/request/MemberHomeInfoGetServiceRequest.java b/src/main/java/com/soptie/server/member/service/dto/request/MemberHomeInfoGetServiceRequest.java deleted file mode 100644 index 6c51d057..00000000 --- a/src/main/java/com/soptie/server/member/service/dto/request/MemberHomeInfoGetServiceRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soptie.server.member.service.dto.request; - -import static lombok.AccessLevel.*; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberHomeInfoGetServiceRequest( - long memberId -) { - - public static MemberHomeInfoGetServiceRequest of(long memberId) { - return MemberHomeInfoGetServiceRequest.builder() - .memberId(memberId) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/member/service/dto/request/MemberProfileCreateServiceRequest.java b/src/main/java/com/soptie/server/member/service/dto/request/MemberProfileCreateServiceRequest.java deleted file mode 100644 index 7d56f1d6..00000000 --- a/src/main/java/com/soptie/server/member/service/dto/request/MemberProfileCreateServiceRequest.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.soptie.server.member.service.dto.request; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.member.controller.dto.request.MemberProfileCreateRequest; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberProfileCreateServiceRequest( - long memberId, - @NonNull DollType dollType, - @NonNull String name, - @NonNull List routines -) { - - public static MemberProfileCreateServiceRequest of(long memberId, MemberProfileCreateRequest request) { - return MemberProfileCreateServiceRequest.builder() - .memberId(memberId) - .dollType(request.dollType()) - .name(request.name()) - .routines(request.routines()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/member/service/dto/response/MemberCottonCountGetServiceResponse.java b/src/main/java/com/soptie/server/member/service/dto/response/MemberCottonCountGetServiceResponse.java deleted file mode 100644 index 72c983dd..00000000 --- a/src/main/java/com/soptie/server/member/service/dto/response/MemberCottonCountGetServiceResponse.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soptie.server.member.service.dto.response; - -import static lombok.AccessLevel.*; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberCottonCountGetServiceResponse( - int cottonCount -) { - - public static MemberCottonCountGetServiceResponse of(int cottonCount) { - return MemberCottonCountGetServiceResponse.builder() - .cottonCount(cottonCount) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/member/service/dto/response/MemberHomeInfoGetServiceResponse.java b/src/main/java/com/soptie/server/member/service/dto/response/MemberHomeInfoGetServiceResponse.java deleted file mode 100644 index 1204d401..00000000 --- a/src/main/java/com/soptie/server/member/service/dto/response/MemberHomeInfoGetServiceResponse.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.soptie.server.member.service.dto.response; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.member.entity.Member; - -import lombok.Builder; -import lombok.NonNull; - -@SuppressWarnings("checkstyle:LineLength") -@Builder(access = PRIVATE) -public record MemberHomeInfoGetServiceResponse( - @NonNull String name, - @NonNull DollType dollType, - @NonNull String frameImageUrl, - int dailyCottonCount, - int happinessCottonCount, - @NonNull List conversations -) { - - public static MemberHomeInfoGetServiceResponse of(Member member, List conversations) { - return MemberHomeInfoGetServiceResponse.builder() - .name(member.getMemberDoll().getName()) - .dollType(member.getMemberDoll().getDoll().getDollType()) - .frameImageUrl(member.getMemberDoll().getDoll().getImageLinks().getFrameImageUrl()) - .dailyCottonCount(member.getCottonInfo().getDailyCottonCount()) - .happinessCottonCount(member.getCottonInfo().getHappinessCottonCount()) - .conversations(conversations) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberdoll/adapter/MemberDollSaver.java b/src/main/java/com/soptie/server/memberdoll/adapter/MemberDollSaver.java deleted file mode 100644 index 1fa5c64e..00000000 --- a/src/main/java/com/soptie/server/memberdoll/adapter/MemberDollSaver.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.soptie.server.memberdoll.adapter; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.memberdoll.entity.MemberDoll; -import com.soptie.server.memberdoll.repository.MemberDollRepository; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class MemberDollSaver { - - private final MemberDollRepository memberDollRepository; - - public void save(MemberDoll memberDoll) { - memberDollRepository.save(memberDoll); - } -} diff --git a/src/main/java/com/soptie/server/memberdoll/entity/MemberDoll.java b/src/main/java/com/soptie/server/memberdoll/entity/MemberDoll.java deleted file mode 100644 index e4ae0154..00000000 --- a/src/main/java/com/soptie/server/memberdoll/entity/MemberDoll.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.soptie.server.memberdoll.entity; - -import static com.soptie.server.common.config.ValueConfig.*; -import static com.soptie.server.doll.message.ErrorCode.*; - -import com.soptie.server.common.entity.BaseTime; -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberdoll.exception.MemberDollException; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToOne; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -@Getter -public class MemberDoll extends BaseTime { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "member_doll_id") - private Long id; - - private String name; - - private int happinessCottonCount; - - @OneToOne(mappedBy = "memberDoll") - private Member member; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "doll_id") - private Doll doll; - - public MemberDoll(Member member, Doll doll, String name) { - this.happinessCottonCount = 0; - setMember(member); - this.doll = doll; - setName(name); - } - - public MemberDoll(Long id) { - this.id = id; - } - - public MemberDoll(Long id, String name, int happinessCottonCount, Doll doll) { - this.id = id; - this.name = name; - this.happinessCottonCount = happinessCottonCount; - this.doll = doll; - } - - private void setMember(Member member) { - this.member = member; - member.registerMemberDoll(this); - } - - private void setName(String name) { - if (!name.matches(MEMBER_DOLL_CONDITION)) { - throw new MemberDollException(INVALID_NAME); - } - this.name = name; - } - - public void addHappinessCottonCount() { - this.happinessCottonCount++; - } -} diff --git a/src/main/java/com/soptie/server/memberdoll/exception/MemberDollException.java b/src/main/java/com/soptie/server/memberdoll/exception/MemberDollException.java deleted file mode 100644 index 193a22a9..00000000 --- a/src/main/java/com/soptie/server/memberdoll/exception/MemberDollException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.memberdoll.exception; - -import com.soptie.server.doll.message.ErrorCode; - -import lombok.Getter; - -@Getter -public class MemberDollException extends RuntimeException { - - private final ErrorCode errorCode; - - public MemberDollException(ErrorCode errorCode) { - super("[MemberDollException] : " + errorCode.getMessage()); - this.errorCode = errorCode; - } -} diff --git a/src/main/java/com/soptie/server/memberdoll/repository/MemberDollRepository.java b/src/main/java/com/soptie/server/memberdoll/repository/MemberDollRepository.java deleted file mode 100644 index f7f4236f..00000000 --- a/src/main/java/com/soptie/server/memberdoll/repository/MemberDollRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soptie.server.memberdoll.repository; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.memberdoll.entity.MemberDoll; - -public interface MemberDollRepository extends JpaRepository { -} diff --git a/src/main/java/com/soptie/server/memberdoll/service/MemberDollService.java b/src/main/java/com/soptie/server/memberdoll/service/MemberDollService.java deleted file mode 100644 index ecd300e3..00000000 --- a/src/main/java/com/soptie/server/memberdoll/service/MemberDollService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.soptie.server.memberdoll.service; - -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberdoll.entity.MemberDoll; - -public interface MemberDollService { - - void createMemberDoll(Member member, DollType dollType, String name); - - void deleteMemberDoll(MemberDoll memberDoll); -} diff --git a/src/main/java/com/soptie/server/memberdoll/service/MemberDollServiceImpl.java b/src/main/java/com/soptie/server/memberdoll/service/MemberDollServiceImpl.java deleted file mode 100644 index 9519cb01..00000000 --- a/src/main/java/com/soptie/server/memberdoll/service/MemberDollServiceImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.soptie.server.memberdoll.service; - -import static com.soptie.server.doll.message.ErrorCode.*; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.doll.exception.DollException; -import com.soptie.server.doll.repository.DollRepository; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberdoll.entity.MemberDoll; -import com.soptie.server.memberdoll.repository.MemberDollRepository; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class MemberDollServiceImpl implements MemberDollService { - - private final MemberDollRepository memberDollRepository; - private final DollRepository dollRepository; - - @Override - @Transactional - public void createMemberDoll(Member member, DollType dollType, String name) { - val doll = findDoll(dollType); - val memberDoll = new MemberDoll(member, doll, name); - memberDollRepository.save(memberDoll); - } - - @Override - @Transactional - public void deleteMemberDoll(MemberDoll memberDoll) { - memberDollRepository.delete(memberDoll); - } - - private Doll findDoll(DollType type) { - return dollRepository.findByDollType(type) - .orElseThrow(() -> new DollException(INVALID_TYPE)); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/adapter/MemberRoutineDeleter.java b/src/main/java/com/soptie/server/memberroutine/adapter/MemberRoutineDeleter.java deleted file mode 100644 index a7ac0739..00000000 --- a/src/main/java/com/soptie/server/memberroutine/adapter/MemberRoutineDeleter.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.soptie.server.memberroutine.adapter; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.entity.DeletedMemberRoutine; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.memberroutine.repository.DeletedMemberRoutineRepository; -import com.soptie.server.memberroutine.repository.MemberRoutineRepository; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class MemberRoutineDeleter { - - private final MemberRoutineRepository memberRoutineRepository; - private final DeletedMemberRoutineRepository deletedMemberRoutineRepository; - - public void softDelete(MemberRoutine memberRoutine) { - deletedMemberRoutineRepository.save(new DeletedMemberRoutine(memberRoutine)); - memberRoutineRepository.delete(memberRoutine); - } - - public void deleteByMember(Member member) { - memberRoutineRepository.deleteByMember(member); - deletedMemberRoutineRepository.deleteByMember(member); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/adapter/MemberRoutineFinder.java b/src/main/java/com/soptie/server/memberroutine/adapter/MemberRoutineFinder.java deleted file mode 100644 index eeddbcbc..00000000 --- a/src/main/java/com/soptie/server/memberroutine/adapter/MemberRoutineFinder.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.soptie.server.memberroutine.adapter; - -import static com.soptie.server.routine.entity.RoutineType.*; -import static com.soptie.server.routine.message.RoutineErrorCode.*; - -import java.util.List; -import java.util.Optional; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.memberroutine.repository.MemberRoutineRepository; -import com.soptie.server.memberroutine.repository.dto.MemberChallengeResponse; -import com.soptie.server.memberroutine.repository.dto.MemberRoutineResponse; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; -import com.soptie.server.routine.exception.RoutineException; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class MemberRoutineFinder { - - private final MemberRoutineRepository memberRoutineRepository; - - public boolean isExist(Member member, Routine routine) { - return memberRoutineRepository.existsByMemberAndTypeAndRoutineId(member, routine.getType(), routine.getId()); - } - - public MemberRoutine findById(long id) { - return memberRoutineRepository.findById(id) - .orElseThrow(() -> new RoutineException(INVALID_ROUTINE)); - } - - public List findAchieved() { - return memberRoutineRepository.findByIsAchieve(true); - } - - public List findAllByMember(Member member) { - return memberRoutineRepository.findByTypeAndMember(DAILY, member); - } - - public boolean existMemberChallenge(Member member) { - return memberRoutineRepository.existsByMemberAndType(member, CHALLENGE); - } - - public Optional findChallengeByMember(Member member) { - return memberRoutineRepository.findChallengeByMember(member); - } - - public List findAllByMemberAndType(Member member, RoutineType type) { - return memberRoutineRepository.findByMemberAndType(member, type); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/adapter/MemberRoutineSaver.java b/src/main/java/com/soptie/server/memberroutine/adapter/MemberRoutineSaver.java deleted file mode 100644 index aeeac143..00000000 --- a/src/main/java/com/soptie/server/memberroutine/adapter/MemberRoutineSaver.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.soptie.server.memberroutine.adapter; - -import static com.soptie.server.routine.entity.RoutineType.*; - -import java.util.Optional; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.entity.DeletedMemberRoutine; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.memberroutine.repository.DeletedMemberRoutineRepository; -import com.soptie.server.memberroutine.repository.MemberRoutineRepository; -import com.soptie.server.routine.entity.Challenge; -import com.soptie.server.routine.entity.Routine; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RepositoryAdapter -@RequiredArgsConstructor -public class MemberRoutineSaver { - - private final MemberRoutineRepository memberRoutineRepository; - private final DeletedMemberRoutineRepository deletedMemberRoutineRepository; - - public MemberRoutine checkHasDeletedAndSave(Member member, Routine routine) { - return findDeleted(member, routine) - .map(this::deleteHistoryAndSave) - .orElseGet(() -> save(new MemberRoutine(member, routine))); - } - - public MemberRoutine checkHasDeletedAndSave(Member member, Challenge challenge) { - return findDeleted(member, challenge) - .map(this::deleteHistoryAndSave) - .orElseGet(() -> save(new MemberRoutine(member, challenge))); - } - - private MemberRoutine save(MemberRoutine memberRoutine) { - return memberRoutineRepository.save(memberRoutine); - } - - private Optional findDeleted(Member member, Routine routine) { - return deletedMemberRoutineRepository - .findByMemberAndTypeAndRoutineId(member, routine.getType(), routine.getId()); - } - - private Optional findDeleted(Member member, Challenge challenge) { - return deletedMemberRoutineRepository - .findByMemberAndTypeAndRoutineId(member, CHALLENGE, challenge.getId()); - } - - private MemberRoutine deleteHistoryAndSave(DeletedMemberRoutine deletedMemberRoutine) { - val memberRoutine = new MemberRoutine(deletedMemberRoutine); - deletedMemberRoutineRepository.delete(deletedMemberRoutine); - return save(memberRoutine); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/MemberDailyRoutineController.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/MemberDailyRoutineController.java deleted file mode 100644 index 06555fcf..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/MemberDailyRoutineController.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1; - -import static com.soptie.server.common.dto.SuccessResponse.*; -import static com.soptie.server.memberroutine.message.MemberRoutineSuccessMassage.*; - -import java.security.Principal; -import java.util.List; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -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.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.BaseResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.common.support.UriGenerator; -import com.soptie.server.memberroutine.controller.v1.docs.MemberDailyRoutineControllerDocs; -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberDailyRoutineCreateRequest; -import com.soptie.server.memberroutine.controller.v1.dto.response.MemberDailyRoutineAchieveResponse; -import com.soptie.server.memberroutine.controller.v1.dto.response.MemberDailyRoutineCreateResponse; -import com.soptie.server.memberroutine.controller.v1.dto.response.MemberDailyRoutineListAcquireResponse; -import com.soptie.server.memberroutine.service.MemberRoutineCreateService; -import com.soptie.server.memberroutine.service.MemberRoutineDeleteService; -import com.soptie.server.memberroutine.service.MemberRoutineReadService; -import com.soptie.server.memberroutine.service.MemberRoutineUpdateService; -import com.soptie.server.memberroutine.service.dto.request.MemberDailyRoutineCreateServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberDailyRoutineListAcquireServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberRoutineAchieveServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberRoutinesDeleteServiceRequest; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/routines/daily/member") -public class MemberDailyRoutineController implements MemberDailyRoutineControllerDocs { - - private final MemberRoutineCreateService memberRoutineCreateService; - private final MemberRoutineReadService memberRoutineReadService; - private final MemberRoutineUpdateService memberRoutineUpdateService; - private final MemberRoutineDeleteService memberRoutineDeleteService; - - @PostMapping - public ResponseEntity> createMemberDailyRoutine( - Principal principal, - @RequestBody MemberDailyRoutineCreateRequest request - ) { - val memberId = Long.parseLong(principal.getName()); - val response = MemberDailyRoutineCreateResponse.of(memberRoutineCreateService.createDailyRoutine( - MemberDailyRoutineCreateServiceRequest.of(memberId, request))); - return ResponseEntity - .created(UriGenerator.getUri("/api/v1/routines/daily/member/", response.routineId())) - .body(success(SUCCESS_CREATE_ROUTINE.getMessage(), response)); - } - - @DeleteMapping - public ResponseEntity deleteMemberDailyRoutines( - Principal principal, - @RequestParam List routines - ) { - val memberId = Long.parseLong(principal.getName()); - memberRoutineDeleteService.deleteMemberRoutines(MemberRoutinesDeleteServiceRequest.of(memberId, routines)); - return ResponseEntity.ok(success(SUCCESS_DELETE_ROUTINE.getMessage())); - } - - @PatchMapping("/routine/{routineId}") - public ResponseEntity> achieveMemberDailyRoutine( - Principal principal, - @PathVariable long routineId - ) { - val memberId = Long.parseLong(principal.getName()); - val response = MemberDailyRoutineAchieveResponse - .of(memberRoutineUpdateService.updateAchievementStatus( - MemberRoutineAchieveServiceRequest.of(memberId, routineId))); - return ResponseEntity.ok(success(SUCCESS_ACHIEVE_ROUTINE.getMessage(), response)); - } - - @GetMapping - public ResponseEntity> getMemberDailyRoutines( - Principal principal - ) { - val memberId = Long.parseLong(principal.getName()); - val response = MemberDailyRoutineListAcquireResponse - .of(memberRoutineReadService.getDailyRoutines(MemberDailyRoutineListAcquireServiceRequest.of(memberId))); - return ResponseEntity.ok(success(SUCCESS_GET_ROUTINE.getMessage(), response)); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/MemberHappinessRoutineController.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/MemberHappinessRoutineController.java deleted file mode 100644 index d0db059f..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/MemberHappinessRoutineController.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1; - -import static com.soptie.server.common.dto.SuccessResponse.*; -import static com.soptie.server.memberroutine.message.MemberRoutineSuccessMassage.*; - -import java.security.Principal; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -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.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.BaseResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.common.support.UriGenerator; -import com.soptie.server.memberroutine.controller.v1.docs.MemberHappinessRoutineControllerDocs; -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberHappinessRoutineRequest; -import com.soptie.server.memberroutine.controller.v1.dto.response.MemberHappinessRoutineCreateResponse; -import com.soptie.server.memberroutine.controller.v1.dto.response.MemberHappinessRoutineGetResponse; -import com.soptie.server.memberroutine.service.MemberRoutineCreateService; -import com.soptie.server.memberroutine.service.MemberRoutineDeleteService; -import com.soptie.server.memberroutine.service.MemberRoutineReadService; -import com.soptie.server.memberroutine.service.MemberRoutineUpdateService; -import com.soptie.server.memberroutine.service.dto.request.MemberHappinessRoutineCreateServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberHappinessRoutineGetServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberRoutineAchieveServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberRoutineDeleteServiceRequest; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/routines/happiness/member") -public class MemberHappinessRoutineController implements MemberHappinessRoutineControllerDocs { - - private final MemberRoutineCreateService memberRoutineCreateService; - private final MemberRoutineReadService memberRoutineReadService; - private final MemberRoutineUpdateService memberRoutineUpdateService; - private final MemberRoutineDeleteService memberRoutineDeleteService; - - @PostMapping - public ResponseEntity> createMemberHappinessRoutine( - Principal principal, @RequestBody MemberHappinessRoutineRequest request) { - val memberId = Long.parseLong(principal.getName()); - val response = MemberHappinessRoutineCreateResponse.of(memberRoutineCreateService.createHappinessRoutine( - MemberHappinessRoutineCreateServiceRequest.of(memberId, request))); - return ResponseEntity - .created(UriGenerator.getUri("/api/v1/routines/happiness/member", response.routineId())) - .body(success(SUCCESS_CREATE_ROUTINE.getMessage(), response)); - } - - @GetMapping - public ResponseEntity getMemberHappinessRoutine(Principal principal) { - val memberId = Long.parseLong(principal.getName()); - return memberRoutineReadService.getHappinessRoutine(MemberHappinessRoutineGetServiceRequest.of(memberId)) - .map(response -> ResponseEntity.ok(SuccessResponse.success( - SUCCESS_GET_ROUTINE.getMessage(), - MemberHappinessRoutineGetResponse.of(response)))) - .orElseGet(() -> ResponseEntity.noContent().build()); - } - - @DeleteMapping("/routine/{routineId}") - public ResponseEntity deleteMemberHappinessRoutine( - Principal principal, - @PathVariable Long routineId - ) { - val memberId = Long.parseLong(principal.getName()); - memberRoutineDeleteService.deleteMemberRoutine(MemberRoutineDeleteServiceRequest.of(memberId, routineId)); - return ResponseEntity.ok(success(SUCCESS_DELETE_ROUTINE.getMessage())); - } - - @PatchMapping("/routine/{routineId}") - public ResponseEntity achieveMemberHappinessRoutine( - Principal principal, - @PathVariable Long routineId - ) { - val memberId = Long.parseLong(principal.getName()); - memberRoutineUpdateService.updateAchievementStatus(MemberRoutineAchieveServiceRequest.of(memberId, routineId)); - return ResponseEntity.ok(success(SUCCESS_ACHIEVE_ROUTINE.getMessage())); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/docs/MemberDailyRoutineControllerDocs.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/docs/MemberDailyRoutineControllerDocs.java deleted file mode 100644 index 1dc6f973..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/docs/MemberDailyRoutineControllerDocs.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1.docs; - -import java.security.Principal; -import java.util.List; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; - -import com.soptie.server.common.dto.BaseResponse; -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberDailyRoutineCreateRequest; -import com.soptie.server.memberroutine.controller.v1.dto.response.MemberDailyRoutineAchieveResponse; -import com.soptie.server.memberroutine.controller.v1.dto.response.MemberDailyRoutineCreateResponse; -import com.soptie.server.memberroutine.controller.v1.dto.response.MemberDailyRoutineListAcquireResponse; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "member daily routines V1", description = "회원의 데일리 루틴 API Version1") -public interface MemberDailyRoutineControllerDocs { - - @Operation( - summary = "데일리 루틴 추가", - description = "회원의 데일리 루틴을 추가한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity> createMemberDailyRoutine( - @Parameter(hidden = true) Principal principal, - @RequestBody MemberDailyRoutineCreateRequest request - ); - - @Operation( - summary = "데일리 루틴 삭제", - description = "회원의 데일리 루틴을 삭제한다.", - responses = { - @ApiResponse( - responseCode = "200", - description = "성공", - content = @Content(schema = @Schema(implementation = SuccessResponse.class))), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity deleteMemberDailyRoutines( - @Parameter(hidden = true) Principal principal, - @Parameter( - name = "routines", - description = "삭제할 회원의 데일리 루틴 id 목록", - in = ParameterIn.QUERY, - example = "1,2,3" - ) @RequestParam List routines - ); - - @Operation( - summary = "데일리 루틴 달성", - description = "회원의 데일리 루틴을 달성한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity> achieveMemberDailyRoutine( - @Parameter(hidden = true) Principal principal, - @Parameter( - name = "routineId", - description = "달성한 회원의 데일리 루틴 id", - in = ParameterIn.PATH, - example = "1" - ) @PathVariable long routineId - ); - - @Operation( - summary = "회원의 데일리 루틴 목록 조회", - description = "회원의 데일리 루틴을 달성 여부, 달성 횟수, 루틴 이름 순으로 정렬된 목록으로 조회한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity> getMemberDailyRoutines( - @Parameter(hidden = true) Principal principal - ); -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/docs/MemberHappinessRoutineControllerDocs.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/docs/MemberHappinessRoutineControllerDocs.java deleted file mode 100644 index bbd26a2a..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/docs/MemberHappinessRoutineControllerDocs.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1.docs; - -import java.security.Principal; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; - -import com.soptie.server.common.dto.BaseResponse; -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberHappinessRoutineRequest; -import com.soptie.server.memberroutine.controller.v1.dto.response.MemberHappinessRoutineCreateResponse; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "member happiness routines V1", description = "회원의 행복 루틴 API Version1") -public interface MemberHappinessRoutineControllerDocs { - - @Operation( - summary = "행복 루틴 추가", - description = "회원의 행복 루틴을 추가한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity> createMemberHappinessRoutine( - @Parameter(hidden = true) Principal principal, - @RequestBody MemberHappinessRoutineRequest request - ); - - @Operation( - summary = "회원의 행복 루틴 목록 조회", - description = "회원의 행복 루틴을 조회한다.", - responses = { - @ApiResponse( - responseCode = "200", - description = "성공", - content = @Content(schema = @Schema(implementation = SuccessResponse.class))), - @ApiResponse( - responseCode = "204", - description = "데이터 없음", - content = @Content(schema = @Schema(implementation = BaseResponse.class))), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity getMemberHappinessRoutine(@Parameter(hidden = true) Principal principal); - - @Operation( - summary = "행복 루틴 삭제", - description = "회원의 행복 루틴을 삭제한다.", - responses = { - @ApiResponse( - responseCode = "200", - description = "성공", - content = @Content(schema = @Schema(implementation = SuccessResponse.class))), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity deleteMemberHappinessRoutine( - @Parameter(hidden = true) Principal principal, - @Parameter( - name = "routineId", - description = "삭제할 회원의 행복 루틴 id", - in = ParameterIn.PATH, - example = "1" - ) - @PathVariable Long routineId - ); - - @Operation( - summary = "행복 루틴 달성", - description = "회원의 행복 루틴을 달성한다.", - responses = { - @ApiResponse( - responseCode = "200", - description = "성공", - content = @Content(schema = @Schema(implementation = SuccessResponse.class))), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity achieveMemberHappinessRoutine( - @Parameter(hidden = true) Principal principal, - @Parameter( - name = "routineId", - description = "달성한 회원의 행복 루틴 id", - in = ParameterIn.PATH, - example = "1" - ) - @PathVariable Long routineId - ); -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/request/MemberDailyRoutineCreateRequest.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/request/MemberDailyRoutineCreateRequest.java deleted file mode 100644 index 6793e309..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/request/MemberDailyRoutineCreateRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1.dto.request; - -public record MemberDailyRoutineCreateRequest( - long routineId -) { -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/request/MemberHappinessRoutineRequest.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/request/MemberHappinessRoutineRequest.java deleted file mode 100644 index 784d73f4..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/request/MemberHappinessRoutineRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1.dto.request; - -public record MemberHappinessRoutineRequest( - long subRoutineId -) { -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberDailyRoutineAchieveResponse.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberDailyRoutineAchieveResponse.java deleted file mode 100644 index 62368037..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberDailyRoutineAchieveResponse.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.service.dto.response.MemberRoutineAchieveServiceResponse; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberDailyRoutineAchieveResponse( - long routineId, - boolean isAchieve, - int achieveCount, - boolean hasCotton -) { - - public static MemberDailyRoutineAchieveResponse of(MemberRoutineAchieveServiceResponse response) { - return MemberDailyRoutineAchieveResponse.builder() - .routineId(response.routineId()) - .isAchieve(response.isAchieve()) - .achieveCount(response.achieveCount()) - .hasCotton(response.hasCotton()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberDailyRoutineCreateResponse.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberDailyRoutineCreateResponse.java deleted file mode 100644 index 977cc0d9..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberDailyRoutineCreateResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutineCreateServiceResponse; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberDailyRoutineCreateResponse( - long routineId -) { - - public static MemberDailyRoutineCreateResponse of(MemberDailyRoutineCreateServiceResponse response) { - return MemberDailyRoutineCreateResponse.builder() - .routineId(response.routineId()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberDailyRoutineListAcquireResponse.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberDailyRoutineListAcquireResponse.java deleted file mode 100644 index 61c8938a..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberDailyRoutineListAcquireResponse.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1.dto.response; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutinesAcquireServiceResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberDailyRoutineListAcquireResponse( - @NonNull List routines -) { - - public static MemberDailyRoutineListAcquireResponse of(MemberDailyRoutinesAcquireServiceResponse response) { - return MemberDailyRoutineListAcquireResponse.builder() - .routines(response.routines().stream().map(MemberDailyRoutineResponse::of).toList()) - .build(); - } - - @Builder(access = PRIVATE) - private record MemberDailyRoutineResponse( - long routineId, - @NonNull String content, - @NonNull String iconImageUrl, - int achieveCount, - boolean isAchieve - ) { - - private static MemberDailyRoutineResponse of( - MemberDailyRoutinesAcquireServiceResponse.MemberDailyRoutineServiceResponse response) { - return MemberDailyRoutineResponse.builder() - .routineId(response.routineId()) - .content(response.content()) - .iconImageUrl(response.iconImageUrl()) - .achieveCount(response.achieveCount()) - .isAchieve(response.isAchieve()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberHappinessRoutineCreateResponse.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberHappinessRoutineCreateResponse.java deleted file mode 100644 index 8d268d83..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberHappinessRoutineCreateResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.service.dto.response.MemberHappinessRoutineCreateServiceResponse; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberHappinessRoutineCreateResponse( - long routineId -) { - - public static MemberHappinessRoutineCreateResponse of(MemberHappinessRoutineCreateServiceResponse response) { - return MemberHappinessRoutineCreateResponse.builder() - .routineId(response.routineId()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberHappinessRoutineGetResponse.java b/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberHappinessRoutineGetResponse.java deleted file mode 100644 index 603db6da..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v1/dto/response/MemberHappinessRoutineGetResponse.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.soptie.server.memberroutine.controller.v1.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.service.dto.response.MemberHappinessRoutineGetServiceResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberHappinessRoutineGetResponse( - long routineId, - @NonNull String iconImageUrl, - @NonNull String contentImageUrl, - @NonNull String themeName, - @NonNull String themeNameColor, - @NonNull String title, - @NonNull String content, - @NonNull String detailContent, - @NonNull String place, - @NonNull String timeTaken -) { - - public static MemberHappinessRoutineGetResponse of(MemberHappinessRoutineGetServiceResponse response) { - return MemberHappinessRoutineGetResponse.builder() - .routineId(response.routineId()) - .iconImageUrl(response.theme().iconImageUrl()) - .contentImageUrl(response.theme().cardImageUrl()) - .themeName(response.theme().name()) - .themeNameColor(response.theme().color()) - .title(response.routineContent()) - .content(response.content()) - .detailContent(response.description()) - .place(response.place()) - .timeTaken(response.requiredTime()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v2/MemberChallengeRoutineControllerV2.java b/src/main/java/com/soptie/server/memberroutine/controller/v2/MemberChallengeRoutineControllerV2.java deleted file mode 100644 index 50e24467..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v2/MemberChallengeRoutineControllerV2.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.soptie.server.memberroutine.controller.v2; - -import static com.soptie.server.memberroutine.message.MemberRoutineSuccessMassage.*; - -import java.security.Principal; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.memberroutine.controller.v2.docs.MemberChallengeRoutineControllerV2Docs; -import com.soptie.server.memberroutine.controller.v2.dto.response.MemberChallengeRoutineAcquireResponseV2; -import com.soptie.server.memberroutine.service.MemberRoutineReadService; -import com.soptie.server.memberroutine.service.dto.request.MemberChallengeRoutineAcquireServiceRequest; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v2/routines/challenge/member") -public class MemberChallengeRoutineControllerV2 implements MemberChallengeRoutineControllerV2Docs { - - private final MemberRoutineReadService memberRoutineReadService; - - @GetMapping - public ResponseEntity acquire(Principal principal) { - val memberId = Long.parseLong(principal.getName()); - return memberRoutineReadService.acquire(MemberChallengeRoutineAcquireServiceRequest.of(memberId)) - .map(response -> ResponseEntity.ok(SuccessResponse.success( - SUCCESS_GET_ROUTINE.getMessage(), - MemberChallengeRoutineAcquireResponseV2.of(response)))) - .orElseGet(() -> ResponseEntity.noContent().build()); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v2/MemberDailyRoutineControllerV2.java b/src/main/java/com/soptie/server/memberroutine/controller/v2/MemberDailyRoutineControllerV2.java deleted file mode 100644 index 0c29580c..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v2/MemberDailyRoutineControllerV2.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.soptie.server.memberroutine.controller.v2; - -import static com.soptie.server.common.dto.SuccessResponse.success; -import static com.soptie.server.memberroutine.message.MemberRoutineSuccessMassage.SUCCESS_CREATE_ROUTINE; -import static com.soptie.server.memberroutine.message.MemberRoutineSuccessMassage.SUCCESS_GET_ROUTINE; - -import java.security.Principal; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberDailyRoutinesCreateRequest; -import com.soptie.server.memberroutine.controller.v2.docs.MemberDailyRoutineControllerV2Docs; -import com.soptie.server.memberroutine.controller.v2.dto.response.MemberDailyRoutineListAcquireResponseV2; -import com.soptie.server.memberroutine.controller.v2.dto.response.MemberDailyRoutinesCreateResponse; -import com.soptie.server.memberroutine.service.MemberRoutineCreateService; -import com.soptie.server.memberroutine.service.MemberRoutineReadService; -import com.soptie.server.memberroutine.service.dto.request.MemberDailyRoutineListAcquireServiceRequest; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v2/routines/daily/member") -public class MemberDailyRoutineControllerV2 implements MemberDailyRoutineControllerV2Docs { - - private final MemberRoutineReadService memberRoutineReadService; - private final MemberRoutineCreateService memberRoutineCreateService; - - @GetMapping - public ResponseEntity> acquireAll( - Principal principal - ) { - val memberId = Long.parseLong(principal.getName()); - val response = MemberDailyRoutineListAcquireResponseV2 - .of(memberRoutineReadService.acquireAll(MemberDailyRoutineListAcquireServiceRequest.of(memberId))); - return ResponseEntity.ok(success(SUCCESS_GET_ROUTINE.getMessage(), response)); - } - - @PostMapping - @ResponseStatus(HttpStatus.CREATED) - public SuccessResponse createMemberDailyRoutines( - Principal principal, - MemberDailyRoutinesCreateRequest request - ) { - val memberId = Long.parseLong(principal.getName()); - val response = MemberDailyRoutinesCreateResponse - .of(memberRoutineCreateService.createDailyRoutines(memberId, request)); - return SuccessResponse.success(SUCCESS_CREATE_ROUTINE.getMessage(), response); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v2/docs/MemberDailyRoutineControllerV2Docs.java b/src/main/java/com/soptie/server/memberroutine/controller/v2/docs/MemberDailyRoutineControllerV2Docs.java deleted file mode 100644 index 39544f05..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v2/docs/MemberDailyRoutineControllerV2Docs.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.soptie.server.memberroutine.controller.v2.docs; - -import java.security.Principal; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestBody; - -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberDailyRoutinesCreateRequest; -import com.soptie.server.memberroutine.controller.v2.dto.response.MemberDailyRoutineListAcquireResponseV2; -import com.soptie.server.memberroutine.controller.v2.dto.response.MemberDailyRoutinesCreateResponse; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "member daily routines V2", description = "회원의 데일리 루틴 API Version2") -public interface MemberDailyRoutineControllerV2Docs { - - @Operation( - summary = "회원의 데일리 루틴 목록 조회", - description = "회원의 데일리 루틴을 무지개 순으로 정렬된 테마와 사전순으로 정렬된 루틴 목록으로 조회한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity> acquireAll( - @Parameter(hidden = true) Principal principal - ); - - @Operation( - summary = "데일리 루틴 다중 추가", - description = "회원의 데일리 루틴을 다중으로 추가한다.", - responses = { - @ApiResponse( - responseCode = "201", - description = "성공", - content = @Content(schema = @Schema(implementation = SuccessResponse.class))), - @ApiResponse( - responseCode = "401", - description = "유효하지 않은 토큰", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - SuccessResponse createMemberDailyRoutines( - @Parameter(hidden = true) Principal principal, - @RequestBody MemberDailyRoutinesCreateRequest request - ); -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v2/dto/response/MemberChallengeRoutineAcquireResponseV2.java b/src/main/java/com/soptie/server/memberroutine/controller/v2/dto/response/MemberChallengeRoutineAcquireResponseV2.java deleted file mode 100644 index d83c0888..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v2/dto/response/MemberChallengeRoutineAcquireResponseV2.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.soptie.server.memberroutine.controller.v2.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.service.dto.response.MemberChallengeRoutineAcquireServiceResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberChallengeRoutineAcquireResponseV2( - long routineId, - long themeId, - @NonNull String themeName, - @NonNull String title, - @NonNull String content, - @NonNull String detailContent, - @NonNull String place, - @NonNull String timeTaken -) { - - public static MemberChallengeRoutineAcquireResponseV2 of(MemberChallengeRoutineAcquireServiceResponse response) { - return MemberChallengeRoutineAcquireResponseV2.builder() - .routineId(response.routineId()) - .themeId(response.theme().themeId()) - .themeName(response.theme().name()) - .title(response.routineContent()) - .content(response.content()) - .detailContent(response.description()) - .place(response.place()) - .timeTaken(response.requiredTime()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v2/dto/response/MemberDailyRoutineListAcquireResponseV2.java b/src/main/java/com/soptie/server/memberroutine/controller/v2/dto/response/MemberDailyRoutineListAcquireResponseV2.java deleted file mode 100644 index b1196a95..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v2/dto/response/MemberDailyRoutineListAcquireResponseV2.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.soptie.server.memberroutine.controller.v2.dto.response; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutineListAcquireServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutinesAcquireServiceResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberDailyRoutineListAcquireResponseV2( - @NonNull List routines -) { - - public static MemberDailyRoutineListAcquireResponseV2 of(MemberDailyRoutineListAcquireServiceResponse response) { - return MemberDailyRoutineListAcquireResponseV2.builder() - .routines(response.routines().stream() - .map(MemberDailyRoutineListResponse::of) - .toList()) - .build(); - } - - @Builder(access = PRIVATE) - public record MemberDailyRoutineListResponse( - long themeId, - @NonNull String themeName, - @NonNull List routines - ) { - - public static MemberDailyRoutineListResponse of(MemberDailyRoutinesAcquireServiceResponse routines) { - return MemberDailyRoutineListResponse.builder() - .themeId(routines.themeId()) - .themeName(routines.themeName()) - .routines(routines.routines().stream().map(MemberDailyRoutineResponse::of).toList()) - .build(); - } - - @Builder(access = PRIVATE) - public record MemberDailyRoutineResponse( - long routineId, - @NonNull String content, - int achieveCount, - boolean isAchieve - ) { - - private static MemberDailyRoutineResponse of( - MemberDailyRoutinesAcquireServiceResponse.MemberDailyRoutineServiceResponse routine - ) { - return MemberDailyRoutineResponse.builder() - .routineId(routine.routineId()) - .content(routine.content()) - .achieveCount(routine.achieveCount()) - .isAchieve(routine.isAchieve()) - .build(); - } - } - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/controller/v2/dto/response/MemberDailyRoutinesCreateResponse.java b/src/main/java/com/soptie/server/memberroutine/controller/v2/dto/response/MemberDailyRoutinesCreateResponse.java deleted file mode 100644 index 7eeb31f9..00000000 --- a/src/main/java/com/soptie/server/memberroutine/controller/v2/dto/response/MemberDailyRoutinesCreateResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.soptie.server.memberroutine.controller.v2.dto.response; - -import static lombok.AccessLevel.PRIVATE; - -import java.util.List; - -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutinesCreateServiceResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberDailyRoutinesCreateResponse( - @NonNull List ids -) { - - public static MemberDailyRoutinesCreateResponse of(MemberDailyRoutinesCreateServiceResponse response) { - return MemberDailyRoutinesCreateResponse.builder() - .ids(response.ids()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/entity/DeletedMemberRoutine.java b/src/main/java/com/soptie/server/memberroutine/entity/DeletedMemberRoutine.java deleted file mode 100644 index 00657f42..00000000 --- a/src/main/java/com/soptie/server/memberroutine/entity/DeletedMemberRoutine.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.soptie.server.memberroutine.entity; - -import static jakarta.persistence.EnumType.*; - -import java.time.LocalDate; - -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.routine.entity.RoutineType; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -@Getter -@EntityListeners(AuditingEntityListener.class) -public class DeletedMemberRoutine { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "deleted_member_routine_id") - private Long id; - - private int achieveCount; - - private boolean isAchieve; - - @Enumerated(value = STRING) - private RoutineType type; - - private long routineId; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id") - private Member member; - - @CreatedDate - private LocalDate createdAt; - - public DeletedMemberRoutine(MemberRoutine memberRoutine) { - this.achieveCount = memberRoutine.getAchieveCount(); - this.isAchieve = memberRoutine.isAchieve(); - this.type = memberRoutine.getType(); - this.routineId = memberRoutine.getRoutineId(); - this.member = memberRoutine.getMember(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/entity/MemberRoutine.java b/src/main/java/com/soptie/server/memberroutine/entity/MemberRoutine.java deleted file mode 100644 index cb7257f3..00000000 --- a/src/main/java/com/soptie/server/memberroutine/entity/MemberRoutine.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.soptie.server.memberroutine.entity; - -import static com.soptie.server.member.message.ErrorCode.*; -import static com.soptie.server.routine.entity.RoutineType.*; -import static jakarta.persistence.EnumType.*; -import static jakarta.persistence.FetchType.*; -import static jakarta.persistence.GenerationType.*; - -import java.time.LocalDate; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.exception.MemberException; -import com.soptie.server.routine.entity.Challenge; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -@Getter -public class MemberRoutine { - - @Id - @GeneratedValue(strategy = IDENTITY) - @Column(name = "member_routine_id") - private Long id; - - private boolean isAchieve; - - private boolean isAchieveToday; - - private int achieveCount; - - @Enumerated(value = STRING) - private RoutineType type; - - private long routineId; - - @ManyToOne(fetch = LAZY) - @JoinColumn(name = "member_id") - private Member member; - - public MemberRoutine(Member member, Routine routine) { - this.isAchieve = false; - this.isAchieveToday = false; - this.achieveCount = 0; - this.type = routine.getType(); - this.routineId = routine.getId(); - this.member = member; - } - - public MemberRoutine(Member member, Challenge challenge) { - this.isAchieve = false; - this.isAchieveToday = false; - this.achieveCount = 0; - this.type = CHALLENGE; - this.routineId = challenge.getId(); - this.member = member; - } - - public MemberRoutine(DeletedMemberRoutine deletedMemberRoutine) { - this.isAchieve = isAchievedToday(deletedMemberRoutine); - this.isAchieveToday = isAchievedToday(deletedMemberRoutine); - this.achieveCount = deletedMemberRoutine.getAchieveCount(); - this.type = deletedMemberRoutine.getType(); - this.routineId = deletedMemberRoutine.getRoutineId(); - this.member = deletedMemberRoutine.getMember(); - } - - public MemberRoutine( - Long id, boolean isAchieve, int achieveCount, - RoutineType type, long routineId, Member member - ) { - this.id = id; - this.isAchieve = isAchieve; - this.isAchieveToday = isAchieve; - this.achieveCount = achieveCount; - this.type = type; - this.routineId = routineId; - this.member = member; - } - - public void achieve() { - this.isAchieve = true; - this.isAchieveToday = true; - this.achieveCount++; - } - - public void initAchieve() { - this.isAchieve = false; - this.isAchieveToday = false; - } - - public void cancelAchievement() { - this.isAchieve = false; - this.achieveCount--; - } - - public void checkMemberHas(Member member) { - if (!this.member.equals(member)) { - throw new MemberException(INACCESSIBLE_ROUTINE); - } - } - - private boolean isAchievedToday(DeletedMemberRoutine deletedMemberRoutine) { - return deletedMemberRoutine.isAchieve() && deletedMemberRoutine.getCreatedAt().equals(LocalDate.now()); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/message/MemberRoutineSuccessMassage.java b/src/main/java/com/soptie/server/memberroutine/message/MemberRoutineSuccessMassage.java deleted file mode 100644 index 348bfe84..00000000 --- a/src/main/java/com/soptie/server/memberroutine/message/MemberRoutineSuccessMassage.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soptie.server.memberroutine.message; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum MemberRoutineSuccessMassage { - SUCCESS_CREATE_ROUTINE("루틴 추가 성공"), - SUCCESS_DELETE_ROUTINE("루틴 삭제 성공"), - SUCCESS_ACHIEVE_ROUTINE("루틴 달성 성공"), - SUCCESS_GET_ROUTINE("루틴 조회 성공"); - - private final String message; -} diff --git a/src/main/java/com/soptie/server/memberroutine/repository/DeletedMemberRoutineRepository.java b/src/main/java/com/soptie/server/memberroutine/repository/DeletedMemberRoutineRepository.java deleted file mode 100644 index 59dc2cd4..00000000 --- a/src/main/java/com/soptie/server/memberroutine/repository/DeletedMemberRoutineRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soptie.server.memberroutine.repository; - -import java.util.Optional; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.entity.DeletedMemberRoutine; -import com.soptie.server.routine.entity.RoutineType; - -public interface DeletedMemberRoutineRepository extends JpaRepository { - Optional findByMemberAndTypeAndRoutineId(Member member, RoutineType type, long routineId); - - boolean existsByMemberAndTypeAndRoutineId(Member member, RoutineType type, long routineId); - - void deleteByMember(Member member); -} diff --git a/src/main/java/com/soptie/server/memberroutine/repository/MemberRoutineCustomRepository.java b/src/main/java/com/soptie/server/memberroutine/repository/MemberRoutineCustomRepository.java deleted file mode 100644 index 458240e5..00000000 --- a/src/main/java/com/soptie/server/memberroutine/repository/MemberRoutineCustomRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soptie.server.memberroutine.repository; - -import java.util.List; -import java.util.Optional; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.repository.dto.MemberChallengeResponse; -import com.soptie.server.memberroutine.repository.dto.MemberRoutineResponse; -import com.soptie.server.routine.entity.RoutineType; - -public interface MemberRoutineCustomRepository { - List findByTypeAndMember(RoutineType type, Member member); - - Optional findChallengeByMember(Member member); -} diff --git a/src/main/java/com/soptie/server/memberroutine/repository/MemberRoutineRepository.java b/src/main/java/com/soptie/server/memberroutine/repository/MemberRoutineRepository.java deleted file mode 100644 index 67c526c4..00000000 --- a/src/main/java/com/soptie/server/memberroutine/repository/MemberRoutineRepository.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.soptie.server.memberroutine.repository; - -import java.util.List; -import java.util.Optional; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.routine.entity.RoutineType; - -public interface MemberRoutineRepository extends JpaRepository, MemberRoutineCustomRepository { - boolean existsByMemberAndTypeAndRoutineId(Member member, RoutineType type, long routineId); - - Optional findByMemberAndTypeAndRoutineId(Member member, RoutineType type, long routineId); - - @SuppressWarnings("SpringDataMethodInconsistencyInspection") - List findByIsAchieve(boolean isAchieve); - - void deleteByMember(Member member); - - boolean existsByMemberAndType(Member member, RoutineType type); - - List findByMemberAndType(Member member, RoutineType type); -} diff --git a/src/main/java/com/soptie/server/memberroutine/repository/MemberRoutineRepositoryImpl.java b/src/main/java/com/soptie/server/memberroutine/repository/MemberRoutineRepositoryImpl.java deleted file mode 100644 index d7b4aa3a..00000000 --- a/src/main/java/com/soptie/server/memberroutine/repository/MemberRoutineRepositoryImpl.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.soptie.server.memberroutine.repository; - -import static com.soptie.server.memberroutine.entity.QMemberRoutine.*; -import static com.soptie.server.routine.entity.QChallenge.*; -import static com.soptie.server.routine.entity.QRoutine.*; -import static com.soptie.server.routine.entity.RoutineType.*; -import static com.soptie.server.theme.entity.QTheme.*; - -import java.util.List; -import java.util.Optional; - -import org.springframework.stereotype.Repository; - -import com.querydsl.jpa.impl.JPAQueryFactory; -import com.soptie.server.common.support.ExpressionGenerator; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.repository.dto.MemberChallengeResponse; -import com.soptie.server.memberroutine.repository.dto.MemberRoutineResponse; -import com.soptie.server.memberroutine.repository.dto.QMemberChallengeResponse; -import com.soptie.server.memberroutine.repository.dto.QMemberRoutineResponse; -import com.soptie.server.routine.entity.RoutineType; - -import lombok.RequiredArgsConstructor; - -@Repository -@RequiredArgsConstructor -public class MemberRoutineRepositoryImpl implements MemberRoutineCustomRepository { - - private final JPAQueryFactory queryFactory; - - @Override - public List findByTypeAndMember(RoutineType type, Member member) { - return queryFactory - .select(new QMemberRoutineResponse(memberRoutine, routine)) - .from(memberRoutine) - .leftJoin(routine).on(memberRoutine.routineId.eq(routine.id)) - .leftJoin(routine.theme, theme).fetchJoin() - .where( - memberRoutine.type.eq(type), - memberRoutine.member.eq(member) - ) - .orderBy( - memberRoutine.isAchieve.asc(), - memberRoutine.achieveCount.desc(), - ExpressionGenerator.getFirstLetter(routine.content).asc() - ) - .fetch(); - } - - @Override - public Optional findChallengeByMember(Member member) { - return Optional.ofNullable(queryFactory - .select(new QMemberChallengeResponse(memberRoutine, challenge, theme)) - .from(memberRoutine) - .leftJoin(challenge).on(memberRoutine.routineId.eq(challenge.id)) - .leftJoin(challenge.routine, routine).fetchJoin() - .leftJoin(challenge.routine.theme, theme).fetchJoin() - .where( - memberRoutine.type.eq(CHALLENGE), - memberRoutine.member.eq(member) - ) - .fetchFirst() - ); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/repository/dto/MemberChallengeResponse.java b/src/main/java/com/soptie/server/memberroutine/repository/dto/MemberChallengeResponse.java deleted file mode 100644 index 71a45257..00000000 --- a/src/main/java/com/soptie/server/memberroutine/repository/dto/MemberChallengeResponse.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.soptie.server.memberroutine.repository.dto; - -import com.querydsl.core.annotations.QueryProjection; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.routine.entity.Challenge; -import com.soptie.server.theme.entity.Theme; - -import lombok.NonNull; - -public record MemberChallengeResponse( - long id, - long challengeId, - @NonNull String routineContent, - @NonNull String content, - @NonNull String description, - @NonNull String place, - @NonNull String requiredTime, - @NonNull Theme theme -) { - - @QueryProjection - public MemberChallengeResponse(MemberRoutine memberRoutine, Challenge challenge, Theme theme) { - this( - memberRoutine.getId(), - challenge.getId(), - challenge.getRoutine().getContent(), - challenge.getContent(), - challenge.getDescription(), - challenge.getPlace(), - challenge.getRequiredTime(), - theme - ); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/repository/dto/MemberRoutineResponse.java b/src/main/java/com/soptie/server/memberroutine/repository/dto/MemberRoutineResponse.java deleted file mode 100644 index 453ceca7..00000000 --- a/src/main/java/com/soptie/server/memberroutine/repository/dto/MemberRoutineResponse.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.soptie.server.memberroutine.repository.dto; - -import com.querydsl.core.annotations.QueryProjection; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.routine.entity.Routine; - -import lombok.NonNull; - -public record MemberRoutineResponse( - long id, - @NonNull String content, - @NonNull String iconImageUrl, - @NonNull String dailyIconImageUrl, - long themeId, - @NonNull String themeName, - int achieveCount, - boolean isAchieve -) { - - @QueryProjection - public MemberRoutineResponse(MemberRoutine memberRoutine, Routine routine) { - this( - memberRoutine.getId(), - routine.getContent(), - routine.getTheme().getImageLinks().getIconImageUrl(), - routine.getTheme().getImageLinks().getDailyIconImageUrl(), - routine.getTheme().getId(), - routine.getTheme().getName(), - memberRoutine.getAchieveCount(), - memberRoutine.isAchieve() - ); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineCreateService.java b/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineCreateService.java deleted file mode 100644 index 79b137bb..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineCreateService.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.soptie.server.memberroutine.service; - -import static com.soptie.server.routine.message.RoutineErrorCode.CANNOT_ADD_MEMBER_ROUTINE; -import static com.soptie.server.routine.message.RoutineErrorCode.DUPLICATED_ROUTINE; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.adapter.MemberRoutineFinder; -import com.soptie.server.memberroutine.adapter.MemberRoutineSaver; -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberDailyRoutinesCreateRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberDailyRoutineCreateServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberHappinessRoutineCreateServiceRequest; -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutineCreateServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutinesCreateServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberHappinessRoutineCreateServiceResponse; -import com.soptie.server.routine.adapter.ChallengeFinder; -import com.soptie.server.routine.adapter.RoutineFinder; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.exception.RoutineException; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional -public class MemberRoutineCreateService { - - private final MemberRoutineSaver memberRoutineSaver; - private final MemberRoutineFinder memberRoutineFinder; - private final MemberFinder memberFinder; - private final RoutineFinder routineFinder; - private final ChallengeFinder challengeFinder; - - public MemberDailyRoutineCreateServiceResponse createDailyRoutine(MemberDailyRoutineCreateServiceRequest request) { - val member = memberFinder.findById(request.memberId()); - val routine = routineFinder.findById(request.routineId()); - checkMemberHasSameRoutineAlready(member, routine); - val savedMemberRoutine = memberRoutineSaver.checkHasDeletedAndSave(member, routine); - return MemberDailyRoutineCreateServiceResponse.of(savedMemberRoutine); - } - - public MemberDailyRoutinesCreateServiceResponse createDailyRoutines( - long memberId, MemberDailyRoutinesCreateRequest request - ) { - val member = memberFinder.findById(memberId); - val routines = routineFinder.findDailyByIds(request.routineIds()); - routines.forEach(routine -> checkMemberHasSameRoutineAlready(member, routine)); - val memberRoutines = routines.stream() - .map(routine -> memberRoutineSaver.checkHasDeletedAndSave(member, routine)) - .toList(); - return MemberDailyRoutinesCreateServiceResponse.of(memberRoutines); - } - - public MemberHappinessRoutineCreateServiceResponse createHappinessRoutine( - MemberHappinessRoutineCreateServiceRequest request - ) { - val member = memberFinder.findById(request.memberId()); - checkMemberHasChallengeAlready(member); - val challenge = challengeFinder.findById(request.challengeId()); - val savedMemberRoutine = memberRoutineSaver.checkHasDeletedAndSave(member, challenge); - return MemberHappinessRoutineCreateServiceResponse.of(savedMemberRoutine); - } - - private void checkMemberHasSameRoutineAlready(Member member, Routine routine) { - if (memberRoutineFinder.isExist(member, routine)) { - throw new RoutineException(DUPLICATED_ROUTINE); - } - } - - private void checkMemberHasChallengeAlready(Member member) { - if (memberRoutineFinder.existMemberChallenge(member)) { - throw new RoutineException(CANNOT_ADD_MEMBER_ROUTINE); - } - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineDeleteService.java b/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineDeleteService.java deleted file mode 100644 index 9f9a5b7f..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineDeleteService.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.soptie.server.memberroutine.service; - -import java.util.List; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.adapter.MemberRoutineDeleter; -import com.soptie.server.memberroutine.adapter.MemberRoutineFinder; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.memberroutine.service.dto.request.MemberRoutineDeleteServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberRoutinesDeleteServiceRequest; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional -public class MemberRoutineDeleteService { - - private final MemberRoutineFinder memberRoutineFinder; - private final MemberRoutineDeleter memberRoutineDeleter; - private final MemberFinder memberFinder; - - public void deleteMemberRoutines(MemberRoutinesDeleteServiceRequest request) { - val member = memberFinder.findById(request.memberId()); - val routines = filterMemberRoutines(member, request.routineIds()); - routines.forEach(memberRoutineDeleter::softDelete); - } - - public void deleteMemberRoutine(MemberRoutineDeleteServiceRequest request) { - val member = memberFinder.findById(request.memberId()); - val memberRoutine = memberRoutineFinder.findById(request.routineId()); - memberRoutine.checkMemberHas(member); - memberRoutineDeleter.softDelete(memberRoutine); - } - - private List filterMemberRoutines(Member member, List routineIds) { - return routineIds.stream() - .map(memberRoutineFinder::findById) - .filter(routine -> routine.getMember().equals(member)) - .toList(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineReadService.java b/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineReadService.java deleted file mode 100644 index abb2a545..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineReadService.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.soptie.server.memberroutine.service; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.memberroutine.adapter.MemberRoutineFinder; -import com.soptie.server.memberroutine.repository.dto.MemberRoutineResponse; -import com.soptie.server.memberroutine.service.dto.request.MemberChallengeRoutineAcquireServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberDailyRoutineListAcquireServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberHappinessRoutineGetServiceRequest; -import com.soptie.server.memberroutine.service.dto.response.MemberChallengeRoutineAcquireServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutineListAcquireServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutinesAcquireServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberHappinessRoutineGetServiceResponse; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class MemberRoutineReadService { - - private final MemberRoutineFinder memberRoutineFinder; - private final MemberFinder memberFinder; - - public MemberDailyRoutinesAcquireServiceResponse getDailyRoutines( - MemberDailyRoutineListAcquireServiceRequest request) { - val member = memberFinder.findById(request.memberId()); - val routines = memberRoutineFinder.findAllByMember(member); - return MemberDailyRoutinesAcquireServiceResponse.of(routines); - } - - public Optional getHappinessRoutine( - MemberHappinessRoutineGetServiceRequest request - ) { - val member = memberFinder.findById(request.memberId()); - val memberRoutine = memberRoutineFinder.findChallengeByMember(member); - return memberRoutine.map(MemberHappinessRoutineGetServiceResponse::of); - } - - public MemberDailyRoutineListAcquireServiceResponse acquireAll( - MemberDailyRoutineListAcquireServiceRequest request) { - val member = memberFinder.findById(request.memberId()); - val routines = memberRoutineFinder.findAllByMember(member); - val routinesWithTheme = collectByTheme(routines); - return MemberDailyRoutineListAcquireServiceResponse.of(routinesWithTheme); - } - - public Optional acquire( - MemberChallengeRoutineAcquireServiceRequest request - ) { - val member = memberFinder.findById(request.memberId()); - val memberRoutine = memberRoutineFinder.findChallengeByMember(member); - return memberRoutine.map(MemberChallengeRoutineAcquireServiceResponse::of); - } - - private List collectByTheme(List routines) { - val routinesByTheme = routines.stream().collect(Collectors.groupingBy(MemberRoutineResponse::themeId)); - return routinesByTheme.values().stream() - .map(MemberDailyRoutinesAcquireServiceResponse::of).toList(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineUpdateService.java b/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineUpdateService.java deleted file mode 100644 index 11e4b9d5..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/MemberRoutineUpdateService.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.soptie.server.memberroutine.service; - -import static com.soptie.server.routine.entity.RoutineType.*; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.memberroutine.adapter.MemberRoutineDeleter; -import com.soptie.server.memberroutine.adapter.MemberRoutineFinder; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.memberroutine.service.dto.request.MemberRoutineAchieveServiceRequest; -import com.soptie.server.memberroutine.service.dto.response.MemberRoutineAchieveServiceResponse; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional -public class MemberRoutineUpdateService { - - private final MemberRoutineFinder memberRoutineFinder; - private final MemberRoutineDeleter memberRoutineDeleter; - private final MemberFinder memberFinder; - - public MemberRoutineAchieveServiceResponse updateAchievementStatus(MemberRoutineAchieveServiceRequest request) { - val member = memberFinder.findById(request.memberId()); - val memberRoutine = memberRoutineFinder.findById(request.memberRoutineId()); - val isAchievedToday = memberRoutine.isAchieveToday(); - - memberRoutine.checkMemberHas(member); - - if (memberRoutine.isAchieve()) { - memberRoutine.cancelAchievement(); - } else { - if (!isAchievedToday) { - member.addCottonCount(memberRoutine.getType()); - } - memberRoutine.achieve(); - deleteMemberRoutineIfTypeIsOneTime(memberRoutine); - } - - return MemberRoutineAchieveServiceResponse.of(memberRoutine, !isAchievedToday); - } - - public void initDailyRoutines() { - val routines = memberRoutineFinder.findAchieved(); - routines.forEach(MemberRoutine::initAchieve); - } - - private void deleteMemberRoutineIfTypeIsOneTime(MemberRoutine memberRoutine) { - if (memberRoutine.getType().equals(CHALLENGE)) { - memberRoutineDeleter.softDelete(memberRoutine); - } - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberChallengeRoutineAcquireServiceRequest.java b/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberChallengeRoutineAcquireServiceRequest.java deleted file mode 100644 index f3089672..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberChallengeRoutineAcquireServiceRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.request; - -import static lombok.AccessLevel.*; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberChallengeRoutineAcquireServiceRequest( - long memberId -) { - - public static MemberChallengeRoutineAcquireServiceRequest of(long memberId) { - return MemberChallengeRoutineAcquireServiceRequest.builder() - .memberId(memberId) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberDailyRoutineCreateServiceRequest.java b/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberDailyRoutineCreateServiceRequest.java deleted file mode 100644 index 189208d9..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberDailyRoutineCreateServiceRequest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.request; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberDailyRoutineCreateRequest; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberDailyRoutineCreateServiceRequest( - long memberId, - long routineId -) { - - public static MemberDailyRoutineCreateServiceRequest of(long memberId, MemberDailyRoutineCreateRequest request) { - return MemberDailyRoutineCreateServiceRequest.builder() - .memberId(memberId) - .routineId(request.routineId()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberDailyRoutineListAcquireServiceRequest.java b/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberDailyRoutineListAcquireServiceRequest.java deleted file mode 100644 index 3f44d5c8..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberDailyRoutineListAcquireServiceRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.request; - -import static lombok.AccessLevel.*; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberDailyRoutineListAcquireServiceRequest( - long memberId -) { - - public static MemberDailyRoutineListAcquireServiceRequest of(long memberId) { - return MemberDailyRoutineListAcquireServiceRequest.builder() - .memberId(memberId) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberHappinessRoutineCreateServiceRequest.java b/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberHappinessRoutineCreateServiceRequest.java deleted file mode 100644 index 889cdd53..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberHappinessRoutineCreateServiceRequest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.request; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberHappinessRoutineRequest; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberHappinessRoutineCreateServiceRequest( - long memberId, - long challengeId -) { - - public static MemberHappinessRoutineCreateServiceRequest of(long memberId, MemberHappinessRoutineRequest request) { - return MemberHappinessRoutineCreateServiceRequest.builder() - .memberId(memberId) - .challengeId(request.subRoutineId()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberHappinessRoutineGetServiceRequest.java b/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberHappinessRoutineGetServiceRequest.java deleted file mode 100644 index fc37a7b0..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberHappinessRoutineGetServiceRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.request; - -import static lombok.AccessLevel.*; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberHappinessRoutineGetServiceRequest( - long memberId -) { - - public static MemberHappinessRoutineGetServiceRequest of(long memberId) { - return MemberHappinessRoutineGetServiceRequest.builder() - .memberId(memberId) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberRoutineAchieveServiceRequest.java b/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberRoutineAchieveServiceRequest.java deleted file mode 100644 index 07f2e94c..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberRoutineAchieveServiceRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.request; - -import static lombok.AccessLevel.*; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberRoutineAchieveServiceRequest( - long memberId, - long memberRoutineId -) { - - public static MemberRoutineAchieveServiceRequest of(long memberId, long memberRoutineId) { - return MemberRoutineAchieveServiceRequest.builder() - .memberId(memberId) - .memberRoutineId(memberRoutineId) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberRoutineDeleteServiceRequest.java b/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberRoutineDeleteServiceRequest.java deleted file mode 100644 index 453f888a..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberRoutineDeleteServiceRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.request; - -import static lombok.AccessLevel.*; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberRoutineDeleteServiceRequest( - long memberId, - long routineId -) { - - public static MemberRoutineDeleteServiceRequest of(long memberId, long routineId) { - return MemberRoutineDeleteServiceRequest.builder() - .memberId(memberId) - .routineId(routineId) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberRoutinesDeleteServiceRequest.java b/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberRoutinesDeleteServiceRequest.java deleted file mode 100644 index e1d8f7f9..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/request/MemberRoutinesDeleteServiceRequest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.request; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberRoutinesDeleteServiceRequest( - long memberId, - List routineIds -) { - - public static MemberRoutinesDeleteServiceRequest of(long memberId, List routineIds) { - return MemberRoutinesDeleteServiceRequest.builder() - .memberId(memberId) - .routineIds(routineIds) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberChallengeRoutineAcquireServiceResponse.java b/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberChallengeRoutineAcquireServiceResponse.java deleted file mode 100644 index 9725f8b0..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberChallengeRoutineAcquireServiceResponse.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.repository.dto.MemberChallengeResponse; -import com.soptie.server.theme.entity.Theme; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberChallengeRoutineAcquireServiceResponse( - long routineId, - ThemeServiceResponse theme, - String routineContent, - String content, - String description, - String place, - String requiredTime -) { - - public static MemberChallengeRoutineAcquireServiceResponse of(MemberChallengeResponse routine) { - return MemberChallengeRoutineAcquireServiceResponse.builder() - .routineId(routine.id()) - .theme(ThemeServiceResponse.of(routine.theme())) - .routineContent(routine.routineContent()) - .content(routine.content()) - .description(routine.description()) - .place(routine.place()) - .requiredTime(routine.requiredTime()) - .build(); - } - - @Builder(access = PRIVATE) - public record ThemeServiceResponse( - long themeId, - String name - ) { - - private static ThemeServiceResponse of(Theme theme) { - return ThemeServiceResponse.builder() - .themeId(theme.getId()) - .name(theme.getName()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutineCreateServiceResponse.java b/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutineCreateServiceResponse.java deleted file mode 100644 index bdfd88e8..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutineCreateServiceResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.entity.MemberRoutine; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberDailyRoutineCreateServiceResponse( - long routineId -) { - - public static MemberDailyRoutineCreateServiceResponse of(MemberRoutine routine) { - return MemberDailyRoutineCreateServiceResponse.builder() - .routineId(routine.getId()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutineListAcquireServiceResponse.java b/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutineListAcquireServiceResponse.java deleted file mode 100644 index f7f3123c..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutineListAcquireServiceResponse.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.response; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberDailyRoutineListAcquireServiceResponse( - @NonNull List routines -) { - - public static MemberDailyRoutineListAcquireServiceResponse of( - List routines) { - return MemberDailyRoutineListAcquireServiceResponse.builder() - .routines(routines) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutinesAcquireServiceResponse.java b/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutinesAcquireServiceResponse.java deleted file mode 100644 index a70b74ab..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutinesAcquireServiceResponse.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.response; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import com.soptie.server.memberroutine.repository.dto.MemberRoutineResponse; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberDailyRoutinesAcquireServiceResponse( - long themeId, - @NonNull String themeName, - @NonNull List routines -) { - - public static MemberDailyRoutinesAcquireServiceResponse of(List routines) { - return MemberDailyRoutinesAcquireServiceResponse.builder() - .themeId(routines.get(0).themeId()) - .themeName(routines.get(0).themeName()) - .routines(routines.stream().map(MemberDailyRoutineServiceResponse::of).toList()) - .build(); - } - - @Builder(access = PRIVATE) - public record MemberDailyRoutineServiceResponse( - long routineId, - @NonNull String content, - @NonNull String iconImageUrl, - int achieveCount, - boolean isAchieve - ) { - - private static MemberDailyRoutineServiceResponse of(MemberRoutineResponse routine) { - return MemberDailyRoutineServiceResponse.builder() - .routineId(routine.id()) - .content(routine.content()) - .iconImageUrl(routine.dailyIconImageUrl()) - .achieveCount(routine.achieveCount()) - .isAchieve(routine.isAchieve()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutinesCreateServiceResponse.java b/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutinesCreateServiceResponse.java deleted file mode 100644 index b049e092..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberDailyRoutinesCreateServiceResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.response; - -import static lombok.AccessLevel.PRIVATE; - -import java.util.List; - -import com.soptie.server.memberroutine.entity.MemberRoutine; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record MemberDailyRoutinesCreateServiceResponse( - @NonNull List ids -) { - - public static MemberDailyRoutinesCreateServiceResponse of(List memberRoutines) { - return MemberDailyRoutinesCreateServiceResponse.builder() - .ids(memberRoutines.stream().map(MemberRoutine::getId).toList()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberHappinessRoutineCreateServiceResponse.java b/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberHappinessRoutineCreateServiceResponse.java deleted file mode 100644 index d798f535..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberHappinessRoutineCreateServiceResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.entity.MemberRoutine; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberHappinessRoutineCreateServiceResponse( - long routineId -) { - - public static MemberHappinessRoutineCreateServiceResponse of(MemberRoutine memberRoutine) { - return MemberHappinessRoutineCreateServiceResponse.builder() - .routineId(memberRoutine.getId()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberHappinessRoutineGetServiceResponse.java b/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberHappinessRoutineGetServiceResponse.java deleted file mode 100644 index 688134f3..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberHappinessRoutineGetServiceResponse.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.repository.dto.MemberChallengeResponse; -import com.soptie.server.theme.entity.Theme; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberHappinessRoutineGetServiceResponse( - long routineId, - ThemeServiceResponse theme, - String routineContent, - String content, - String description, - String place, - String requiredTime -) { - - public static MemberHappinessRoutineGetServiceResponse of(MemberChallengeResponse routine) { - return MemberHappinessRoutineGetServiceResponse.builder() - .routineId(routine.id()) - .theme(ThemeServiceResponse.of(routine.theme())) - .routineContent(routine.routineContent()) - .content(routine.content()) - .description(routine.description()) - .place(routine.place()) - .requiredTime(routine.requiredTime()) - .build(); - } - - @Builder(access = PRIVATE) - public record ThemeServiceResponse( - String iconImageUrl, - String cardImageUrl, - String name, - String color - ) { - - private static ThemeServiceResponse of(Theme theme) { - return ThemeServiceResponse.builder() - .iconImageUrl(theme.getImageLinks().getIconImageUrl()) - .cardImageUrl(theme.getImageLinks().getHappinessCardImageUrl()) - .name(theme.getName()) - .color(theme.getColor()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberRoutineAchieveServiceResponse.java b/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberRoutineAchieveServiceResponse.java deleted file mode 100644 index 5f5ac920..00000000 --- a/src/main/java/com/soptie/server/memberroutine/service/dto/response/MemberRoutineAchieveServiceResponse.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.soptie.server.memberroutine.service.dto.response; - -import static lombok.AccessLevel.*; - -import com.soptie.server.memberroutine.entity.MemberRoutine; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record MemberRoutineAchieveServiceResponse( - long routineId, - boolean isAchieve, - int achieveCount, - boolean hasCotton -) { - - public static MemberRoutineAchieveServiceResponse of(MemberRoutine routine, boolean hasCotton) { - return MemberRoutineAchieveServiceResponse.builder() - .routineId(routine.getId()) - .isAchieve(routine.isAchieve()) - .achieveCount(routine.getAchieveCount()) - .hasCotton(hasCotton) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/persistence/adapter/ChallengeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/ChallengeAdapter.java new file mode 100644 index 00000000..10db06cf --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/ChallengeAdapter.java @@ -0,0 +1,31 @@ +package com.soptie.server.persistence.adapter; + +import java.util.List; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.challenge.Challenge; +import com.soptie.server.persistence.entity.ChallengeEntity; +import com.soptie.server.persistence.repository.ChallengeRepository; + +import lombok.RequiredArgsConstructor; + +@RepositoryAdapter +@RequiredArgsConstructor +public class ChallengeAdapter { + private final ChallengeRepository challengeRepository; + + public List findByThemeId(long themeId) { + return challengeRepository.findByThemeId(themeId).stream().map(ChallengeEntity::toDomain).toList(); + } + + public Challenge findById(long challengeId) { + return find(challengeId).toDomain(); + } + + private ChallengeEntity find(long id) { + return challengeRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Challenge ID: " + id)); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/ConversationAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/ConversationAdapter.java new file mode 100644 index 00000000..5f6c1cca --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/ConversationAdapter.java @@ -0,0 +1,20 @@ +package com.soptie.server.persistence.adapter; + +import java.util.List; + +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.conversation.Conversation; +import com.soptie.server.persistence.entity.ConversationEntity; +import com.soptie.server.persistence.repository.ConversationRepository; + +import lombok.RequiredArgsConstructor; + +@RepositoryAdapter +@RequiredArgsConstructor +public class ConversationAdapter { + private final ConversationRepository conversationRepository; + + public List findAll() { + return conversationRepository.findAll().stream().map(ConversationEntity::toDomain).toList(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/DollAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/DollAdapter.java new file mode 100644 index 00000000..32824c8d --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/DollAdapter.java @@ -0,0 +1,22 @@ +package com.soptie.server.persistence.adapter; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.doll.Doll; +import com.soptie.server.domain.doll.DollType; +import com.soptie.server.persistence.repository.DollRepository; + +import lombok.RequiredArgsConstructor; + +@RepositoryAdapter +@RequiredArgsConstructor +public class DollAdapter { + private final DollRepository dollRepository; + + public Doll findByType(DollType type) { + return dollRepository.findByType(type) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Doll Type: " + type)) + .toDomain(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/MakerAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/MakerAdapter.java new file mode 100644 index 00000000..ba128d3b --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/MakerAdapter.java @@ -0,0 +1,14 @@ +package com.soptie.server.persistence.adapter; + +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.persistence.repository.MakerRepository; + +import lombok.RequiredArgsConstructor; + +@RepositoryAdapter +@RequiredArgsConstructor +public class MakerAdapter { + + private final MakerRepository makerRepository; + +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/MemberAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/MemberAdapter.java new file mode 100644 index 00000000..2b86454c --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/MemberAdapter.java @@ -0,0 +1,54 @@ +package com.soptie.server.persistence.adapter; + +import java.util.Optional; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.member.SocialType; +import com.soptie.server.persistence.entity.MemberEntity; +import com.soptie.server.persistence.repository.MemberRepository; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RepositoryAdapter +@RequiredArgsConstructor +public class MemberAdapter { + + private final MemberRepository memberRepository; + + public Optional findBySocialTypeAndSocialId(SocialType socialType, String socialId) { + return memberRepository.findBySocialTypeAndSocialId(socialType, socialId) + .map(MemberEntity::toDomain); + } + + public Member save(SocialType socialType, String socialId) { + return memberRepository.save(new MemberEntity(socialType, socialId)).toDomain(); + } + + public Member findByRefreshToken(String refreshToken) { + return memberRepository.findByRefreshToken(refreshToken) + .map(MemberEntity::toDomain) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND)); + } + + public void delete(long memberId) { + memberRepository.deleteById(memberId); + } + + public Member findById(long memberId) { + return find(memberId).toDomain(); + } + + public void update(Member member) { + val memberEntity = find(member.getId()); + memberEntity.update(member); + } + + private MemberEntity find(long id) { + return memberRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Member ID: " + id)); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/MemberDollAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/MemberDollAdapter.java new file mode 100644 index 00000000..e1853781 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/MemberDollAdapter.java @@ -0,0 +1,47 @@ +package com.soptie.server.persistence.adapter; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.memberdoll.MemberDoll; +import com.soptie.server.persistence.entity.MemberDollEntity; +import com.soptie.server.persistence.repository.MemberDollRepository; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RepositoryAdapter +@RequiredArgsConstructor +public class MemberDollAdapter { + private final MemberDollRepository memberDollRepository; + + public void save(MemberDoll memberDoll) { + memberDollRepository.save(new MemberDollEntity(memberDoll)); + } + + public boolean isExistByMember(long memberId) { + return memberDollRepository.existsByMemberId(memberId); + } + + public MemberDoll findByMember(long memberId) { + return memberDollRepository.findByMemberId(memberId) + .orElseThrow(() -> new SoftieException( + ExceptionCode.NOT_FOUND, + "Not Found MemberDoll, Member ID: " + memberId)) + .toDomain(); + } + + public void update(MemberDoll memberDoll) { + val memberDollEntity = find(memberDoll.getId()); + memberDollEntity.update(memberDoll); + } + + public void deleteByMember(long memberId) { + memberDollRepository.deleteByMemberId(memberId); + } + + private MemberDollEntity find(long id) { + return memberDollRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "MemberDoll ID: " + id)); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/MemberMissionAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/MemberMissionAdapter.java new file mode 100644 index 00000000..494bb8f1 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/MemberMissionAdapter.java @@ -0,0 +1,79 @@ +package com.soptie.server.persistence.adapter; + +import java.util.List; +import java.util.Optional; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.challenge.Mission; +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.membermission.MemberMission; +import com.soptie.server.persistence.entity.MemberMissionEntity; +import com.soptie.server.persistence.repository.MemberMissionRepository; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RepositoryAdapter +@RequiredArgsConstructor +public class MemberMissionAdapter { + private final MemberMissionRepository memberMissionRepository; + + public List findByMemberIdAndMissionIds(long memberId, List missionIds) { + return memberMissionRepository.findByMemberIdAndMissionIdIn(memberId, missionIds) + .stream().map(MemberMissionEntity::toDomain) + .toList(); + } + + public void deleteAllByMemberId(long memberId) { + memberMissionRepository.deleteAllByMemberId(memberId); + } + + public Optional findByMember(long memberId) { + return memberMissionRepository.findByMemberId(memberId).map(MemberMissionEntity::toDomain); + } + + public void delete(MemberMission memberMission) { + val memberMissionEntity = find(memberMission.getId()); + memberMissionRepository.delete(memberMissionEntity); + } + + public void update(MemberMission memberMission) { + val memberMissionEntity = find(memberMission.getId()); + memberMissionEntity.update(memberMission); + } + + public MemberMission save(Member member, Mission mission) { + val deletedMemberMissions = memberMissionRepository.findDeletedByMemberId(member.getId()); + val deletedMemberMissionIds = deletedMemberMissions.stream().map(MemberMissionEntity::getMissionId).toList(); + return (deletedMemberMissionIds.contains(mission.getId()) + ? restore(deletedMemberMissions, member, mission) + : memberMissionRepository.save(new MemberMissionEntity(member, mission))) + .toDomain(); + } + + public void flush() { + memberMissionRepository.flush(); + } + + private MemberMissionEntity restore( + List deletedMemberMissions, + Member member, + Mission mission + ) { + val deletedMemberMission = deletedMemberMissions.stream() + .filter(mm -> mm.getMissionId() == mission.getId()) + .findFirst() + .orElseThrow(() -> new SoftieException( + ExceptionCode.NOT_FOUND, + "Member ID: " + member.getId() + " Mission ID: " + mission.getId())); + deletedMemberMission.restore(); + return deletedMemberMission; + } + + private MemberMissionEntity find(long id) { + return memberMissionRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "MemberMission ID: " + id)); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/MemberRoutineAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/MemberRoutineAdapter.java new file mode 100644 index 00000000..5859451c --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/MemberRoutineAdapter.java @@ -0,0 +1,92 @@ +package com.soptie.server.persistence.adapter; + +import java.util.ArrayList; +import java.util.List; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.memberroutine.MemberRoutine; +import com.soptie.server.domain.routine.Routine; +import com.soptie.server.persistence.entity.MemberRoutineEntity; +import com.soptie.server.persistence.repository.MemberRoutineRepository; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RepositoryAdapter +@RequiredArgsConstructor +public class MemberRoutineAdapter { + + private final MemberRoutineRepository memberRoutineRepository; + + public List saveAll(Member member, List routines) { + val deletedMemberRoutines = memberRoutineRepository.findDeletedByMemberId(member.getId()); + val deletedRoutineIds = deletedMemberRoutines + .stream().map(MemberRoutineEntity::getRoutineId) + .toList(); + + return routines.stream() + .map(routine -> deletedRoutineIds.contains(routine.getId()) + ? restore(deletedMemberRoutines, member, routine).toDomain() + : memberRoutineRepository.save(new MemberRoutineEntity(member, routine)).toDomain()) + .toList(); + } + + public List findByMemberId(long memberId) { + return memberRoutineRepository.findByMemberId(memberId).stream().map(MemberRoutineEntity::toDomain).toList(); + } + + public List findByIds(List ids) { + return memberRoutineRepository.findByIdIn(ids).stream().map(MemberRoutineEntity::toDomain).toList(); + } + + public void deleteAll(List memberRoutines) { + val memberRoutineIds = memberRoutines.stream().map(MemberRoutine::getId).toList(); + memberRoutineRepository.deleteAllByIdIn(memberRoutineIds); + } + + public void deleteAllByMemberId(long memberId) { + memberRoutineRepository.deleteAllByMemberId(memberId); + } + + public MemberRoutine findById(long memberRoutineId) { + return find(memberRoutineId).toDomain(); + } + + public void update(MemberRoutine memberRoutine) { + val memberRoutineEntity = find(memberRoutine.getId()); + memberRoutineEntity.update(memberRoutine); + } + + public List findAchieved() { + val memberRoutines = new ArrayList(); + memberRoutines.addAll(memberRoutineRepository.findByIsAchieved(true).stream() + .map(MemberRoutineEntity::toDomain) + .toList()); + memberRoutines.addAll(memberRoutineRepository.findDeletedByIsAchieved(true).stream().map( + MemberRoutineEntity::toDomain).toList()); + return memberRoutines; + } + + private MemberRoutineEntity restore( + List deletedMemberRoutines, + Member member, + Routine routine + ) { + val deletedMemberRoutine = deletedMemberRoutines.stream() + .filter(mr -> mr.getRoutineId() == routine.getId()) + .findFirst() + .orElseThrow(() -> new SoftieException( + ExceptionCode.NOT_FOUND, + "Member ID: " + member.getId() + " Routine ID: " + routine.getId())); + deletedMemberRoutine.restore(); + return deletedMemberRoutine; + } + + private MemberRoutineEntity find(long id) { + return memberRoutineRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "MemberRoutine ID: " + id)); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/MissionAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/MissionAdapter.java new file mode 100644 index 00000000..361e2eec --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/MissionAdapter.java @@ -0,0 +1,33 @@ +package com.soptie.server.persistence.adapter; + +import java.util.List; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.challenge.Mission; +import com.soptie.server.persistence.entity.MissionEntity; +import com.soptie.server.persistence.repository.MissionRepository; + +import lombok.RequiredArgsConstructor; + +@RepositoryAdapter +@RequiredArgsConstructor +public class MissionAdapter { + private final MissionRepository missionRepository; + + public List findByChallengeIds(List challengeIds) { + return missionRepository.findByChallengeIdIn(challengeIds) + .stream().map(MissionEntity::toDomain) + .toList(); + } + + public Mission findById(long missionId) { + return find(missionId).toDomain(); + } + + private MissionEntity find(long id) { + return missionRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Mission ID: " + id)); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/RoutineAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/RoutineAdapter.java new file mode 100644 index 00000000..19ad311f --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/RoutineAdapter.java @@ -0,0 +1,37 @@ +package com.soptie.server.persistence.adapter; + +import java.util.List; + +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.routine.Routine; +import com.soptie.server.persistence.entity.RoutineEntity; +import com.soptie.server.persistence.repository.RoutineRepository; + +import lombok.RequiredArgsConstructor; + +@RepositoryAdapter +@RequiredArgsConstructor +public class RoutineAdapter { + private final RoutineRepository routineRepository; + + public List findByIds(List ids) { + return routineRepository.findByIdIn(ids).stream().map(RoutineEntity::toDomain).toList(); + } + + public List findByThemeId(long themeId) { + return routineRepository.findByThemeIdOrderByContentAsc(themeId).stream() + .map(RoutineEntity::toDomain) + .toList(); + } + + public Routine findById(long id) { + return find(id).toDomain(); + } + + private RoutineEntity find(long id) { + return routineRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Routine ID: " + id)); + } +} diff --git a/src/main/java/com/soptie/server/persistence/adapter/ThemeAdapter.java b/src/main/java/com/soptie/server/persistence/adapter/ThemeAdapter.java new file mode 100644 index 00000000..c4c9a1bd --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/adapter/ThemeAdapter.java @@ -0,0 +1,49 @@ +package com.soptie.server.persistence.adapter; + +import java.util.List; + +import com.soptie.server.api.controller.dto.response.maker.MakerThemeResponse; +import com.soptie.server.common.exception.ExceptionCode; +import com.soptie.server.common.exception.SoftieException; +import com.soptie.server.common.support.RepositoryAdapter; +import com.soptie.server.domain.theme.Theme; +import com.soptie.server.persistence.entity.ThemeEntity; +import com.soptie.server.persistence.repository.ThemeRepository; + +import lombok.RequiredArgsConstructor; + +@RepositoryAdapter +@RequiredArgsConstructor +public class ThemeAdapter { + + private final ThemeRepository themeRepository; + + public List findByBasic() { + return themeRepository.findByMakerIdIsNullOrderBySequenceAsc() + .stream().map(ThemeEntity::toDomain) + .toList(); + } + + public List findAllWithMaker() { + return themeRepository.findAllWithMaker(); + } + + public Theme findById(long id) { + return find(id).toDomain(); + } + + public List findByIds(List ids) { + return themeRepository.findByIdIn(ids) + .stream().map(ThemeEntity::toDomain) + .toList(); + } + + public boolean isExistById(long id) { + return themeRepository.existsById(id); + } + + private ThemeEntity find(long id) { + return themeRepository.findById(id) + .orElseThrow(() -> new SoftieException(ExceptionCode.NOT_FOUND, "Theme ID: " + id)); + } +} diff --git a/src/main/java/com/soptie/server/common/config/JpaAuditingConfig.java b/src/main/java/com/soptie/server/persistence/config/JpaAuditingConfig.java similarity index 81% rename from src/main/java/com/soptie/server/common/config/JpaAuditingConfig.java rename to src/main/java/com/soptie/server/persistence/config/JpaAuditingConfig.java index 9a4b314c..2c6b8964 100644 --- a/src/main/java/com/soptie/server/common/config/JpaAuditingConfig.java +++ b/src/main/java/com/soptie/server/persistence/config/JpaAuditingConfig.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.config; +package com.soptie.server.persistence.config; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; diff --git a/src/main/java/com/soptie/server/common/config/JpaQueryFactoryConfig.java b/src/main/java/com/soptie/server/persistence/config/JpaQueryFactoryConfig.java similarity index 88% rename from src/main/java/com/soptie/server/common/config/JpaQueryFactoryConfig.java rename to src/main/java/com/soptie/server/persistence/config/JpaQueryFactoryConfig.java index 1d53ad24..ed9b005e 100644 --- a/src/main/java/com/soptie/server/common/config/JpaQueryFactoryConfig.java +++ b/src/main/java/com/soptie/server/persistence/config/JpaQueryFactoryConfig.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.config; +package com.soptie.server.persistence.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/soptie/server/common/config/TimezoneConfig.java b/src/main/java/com/soptie/server/persistence/config/TimezoneConfig.java similarity index 85% rename from src/main/java/com/soptie/server/common/config/TimezoneConfig.java rename to src/main/java/com/soptie/server/persistence/config/TimezoneConfig.java index 74bee708..e53925fb 100644 --- a/src/main/java/com/soptie/server/common/config/TimezoneConfig.java +++ b/src/main/java/com/soptie/server/persistence/config/TimezoneConfig.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.config; +package com.soptie.server.persistence.config; import java.util.TimeZone; diff --git a/src/main/java/com/soptie/server/common/entity/BaseTime.java b/src/main/java/com/soptie/server/persistence/entity/BaseEntity.java similarity index 64% rename from src/main/java/com/soptie/server/common/entity/BaseTime.java rename to src/main/java/com/soptie/server/persistence/entity/BaseEntity.java index db8aa132..e39eedc1 100644 --- a/src/main/java/com/soptie/server/common/entity/BaseTime.java +++ b/src/main/java/com/soptie/server/persistence/entity/BaseEntity.java @@ -1,4 +1,4 @@ -package com.soptie.server.common.entity; +package com.soptie.server.persistence.entity; import java.time.LocalDateTime; @@ -7,18 +7,21 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import jakarta.persistence.EntityListeners; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import jakarta.persistence.MappedSuperclass; -import lombok.Getter; @MappedSuperclass @EntityListeners(AuditingEntityListener.class) -@Getter -public class BaseTime { +public class BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + protected Long id; @CreatedDate protected LocalDateTime createdAt; @LastModifiedDate protected LocalDateTime updatedAt; - } diff --git a/src/main/java/com/soptie/server/persistence/entity/ChallengeEntity.java b/src/main/java/com/soptie/server/persistence/entity/ChallengeEntity.java new file mode 100644 index 00000000..3b5347ee --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/ChallengeEntity.java @@ -0,0 +1,24 @@ +package com.soptie.server.persistence.entity; + +import com.soptie.server.domain.challenge.Challenge; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +@Entity +@Table(name = "challenge", schema = "softie") +public class ChallengeEntity extends BaseEntity { + @Column(nullable = false) + private String name; + @Column(nullable = false) + private long themeId; + + public Challenge toDomain() { + return Challenge.builder() + .id(this.id) + .name(this.name) + .themeId(this.themeId) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/ConversationEntity.java b/src/main/java/com/soptie/server/persistence/entity/ConversationEntity.java new file mode 100644 index 00000000..90792547 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/ConversationEntity.java @@ -0,0 +1,21 @@ +package com.soptie.server.persistence.entity; + +import com.soptie.server.domain.conversation.Conversation; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +@Entity +@Table(name = "conversation", schema = "softie") +public class ConversationEntity extends BaseEntity { + @Column(nullable = false) + private String content; + + public Conversation toDomain() { + return Conversation.builder() + .id(this.id) + .content(this.content) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/DollEntity.java b/src/main/java/com/soptie/server/persistence/entity/DollEntity.java new file mode 100644 index 00000000..57a2395f --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/DollEntity.java @@ -0,0 +1,25 @@ +package com.soptie.server.persistence.entity; + +import com.soptie.server.domain.doll.Doll; +import com.soptie.server.domain.doll.DollType; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; + +@Entity +@Table(name = "doll", schema = "softie") +public class DollEntity extends BaseEntity { + @Enumerated(value = EnumType.STRING) + @Column(nullable = false) + private DollType type; + + public Doll toDomain() { + return Doll.builder() + .id(this.id) + .type(this.type) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/MakerEntity.java b/src/main/java/com/soptie/server/persistence/entity/MakerEntity.java new file mode 100644 index 00000000..d51af0e7 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/MakerEntity.java @@ -0,0 +1,38 @@ +package com.soptie.server.persistence.entity; + +import com.soptie.server.domain.maker.Maker; +import com.soptie.server.domain.maker.Tags; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "maker", schema = "softie") +public class MakerEntity extends BaseEntity { + @Column(nullable = false) + private String name; + private String introductionUrl; + private String profileImageUrl; + private String tags; + + public MakerEntity(Maker maker) { + this.name = maker.getName(); + this.introductionUrl = maker.getIntroductionUrl(); + this.profileImageUrl = maker.getProfileImageUrl(); + this.tags = maker.getTags().getContents(); + } + + public Maker toDomain() { + return Maker.builder() + .id(this.id) + .name(this.name) + .introductionUrl(this.introductionUrl) + .profileImageUrl(this.profileImageUrl) + .tags(new Tags(tags)) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/MemberDollEntity.java b/src/main/java/com/soptie/server/persistence/entity/MemberDollEntity.java new file mode 100644 index 00000000..480c5f73 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/MemberDollEntity.java @@ -0,0 +1,67 @@ +package com.soptie.server.persistence.entity; + +import com.soptie.server.domain.doll.DollType; +import com.soptie.server.domain.memberdoll.DollCotton; +import com.soptie.server.domain.memberdoll.MemberDoll; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@Entity +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "member_doll", schema = "softie") +public class MemberDollEntity extends BaseEntity { + @Column(nullable = false) + private String name; + @Enumerated(value = EnumType.STRING) + @Column(nullable = false) + private DollType dollType; + @Column(nullable = false) + private int basicCottonCount; + @Column(nullable = false) + private int rainbowCottonCount; + @Column(nullable = false, unique = true) + private long memberId; + @Column(nullable = false) + private long dollId; + + public MemberDollEntity(MemberDoll memberDoll) { + this.name = memberDoll.getName(); + this.dollType = memberDoll.getDollType(); + this.basicCottonCount = 0; + this.rainbowCottonCount = 0; + this.memberId = memberDoll.getMemberId(); + this.dollId = memberDoll.getDollId(); + } + + public MemberDoll toDomain() { + return MemberDoll.builder() + .id(this.id) + .dollType(this.dollType) + .name(this.name) + .cottonInfo(toCottonInfo()) + .memberId(memberId) + .dollId(dollId) + .build(); + } + + public void update(MemberDoll memberDoll) { + this.name = memberDoll.getName(); + this.basicCottonCount = memberDoll.getCottonInfo().getBasicCottonCount(); + this.rainbowCottonCount = memberDoll.getCottonInfo().getRainbowCottonCount(); + } + + private DollCotton toCottonInfo() { + return DollCotton.builder() + .basicCottonCount(this.basicCottonCount) + .rainbowCottonCount(this.rainbowCottonCount) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/MemberEntity.java b/src/main/java/com/soptie/server/persistence/entity/MemberEntity.java new file mode 100644 index 00000000..c13ff89a --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/MemberEntity.java @@ -0,0 +1,66 @@ +package com.soptie.server.persistence.entity; + +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.member.MemberCotton; +import com.soptie.server.domain.member.Social; +import com.soptie.server.domain.member.SocialType; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "member", schema = "softie") +public class MemberEntity extends BaseEntity { + @Enumerated(value = EnumType.STRING) + @Column(nullable = false) + private SocialType socialType; + @Column(nullable = false) + private String socialId; + private String refreshToken; + @Column(nullable = false) + private int basicCottonCount; + @Column(nullable = false) + private int rainbowCottonCount; + + public MemberEntity(SocialType socialType, String socialId) { + this.socialType = socialType; + this.socialId = socialId; + this.basicCottonCount = 0; + this.rainbowCottonCount = 0; + } + + public void update(Member member) { + this.refreshToken = member.getRefreshToken(); + this.basicCottonCount = member.getCottonInfo().getBasicCottonCount(); + this.rainbowCottonCount = member.getCottonInfo().getRainbowCottonCount(); + } + + public Member toDomain() { + return Member.builder() + .id(this.id) + .socialInfo(toSocialInfo()) + .refreshToken(this.refreshToken) + .cottonInfo(toCottonInfo()) + .build(); + } + + private Social toSocialInfo() { + return Social.builder() + .socialType(this.socialType) + .socialId(this.socialId) + .build(); + } + + private MemberCotton toCottonInfo() { + return MemberCotton.builder() + .basicCottonCount(this.basicCottonCount) + .rainbowCottonCount(this.rainbowCottonCount) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/MemberMissionEntity.java b/src/main/java/com/soptie/server/persistence/entity/MemberMissionEntity.java new file mode 100644 index 00000000..184dff23 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/MemberMissionEntity.java @@ -0,0 +1,59 @@ +package com.soptie.server.persistence.entity; + +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; + +import com.soptie.server.domain.challenge.Mission; +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.membermission.MemberMission; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@SQLRestriction("is_deleted = false") +@SQLDelete(sql = "UPDATE softie.member_mission SET is_deleted = true WHERE id = ?") +@Table( + name = "member_mission", + schema = "softie", + uniqueConstraints = @UniqueConstraint(columnNames = {"member_id", "mission_id"})) +public class MemberMissionEntity extends BaseEntity { + @Column(nullable = false) + private int achievementCount; + @Column(nullable = false) + private boolean isDeleted; + @Column(nullable = false) + private long memberId; + @Column(nullable = false) + private long missionId; + + public MemberMissionEntity(Member member, Mission mission) { + this.achievementCount = 0; + this.memberId = member.getId(); + this.missionId = mission.getId(); + } + + public MemberMission toDomain() { + return MemberMission.builder() + .id(this.id) + .achievementCount(this.achievementCount) + .memberId(this.memberId) + .missionId(this.missionId) + .build(); + } + + public void update(MemberMission memberMission) { + this.achievementCount += memberMission.getAchievementCount(); + } + + public void restore() { + this.isDeleted = false; + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/MemberRoutineEntity.java b/src/main/java/com/soptie/server/persistence/entity/MemberRoutineEntity.java new file mode 100644 index 00000000..2e5b3657 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/MemberRoutineEntity.java @@ -0,0 +1,70 @@ +package com.soptie.server.persistence.entity; + +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.SQLRestriction; + +import com.soptie.server.domain.member.Member; +import com.soptie.server.domain.memberroutine.MemberRoutine; +import com.soptie.server.domain.routine.Routine; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@SQLRestriction("is_deleted = false") +@SQLDelete(sql = "UPDATE softie.member_routine SET is_deleted = true WHERE id = ?") +@Table( + name = "member_routine", + schema = "softie", + uniqueConstraints = @UniqueConstraint(columnNames = {"member_id", "routine_id"})) +public class MemberRoutineEntity extends BaseEntity { + @Column(nullable = false) + private boolean isAchieved; + @Column(nullable = false) + private boolean isAchievedToday; + @Column(nullable = false) + private int achievementCount; + @Column(nullable = false) + private boolean isDeleted; + @Column(nullable = false) + private long memberId; + @Column(nullable = false) + private long routineId; + + public MemberRoutineEntity(Member member, Routine routine) { + this.isAchieved = false; + this.isAchievedToday = false; + this.achievementCount = 0; + this.isDeleted = false; + this.memberId = member.getId(); + this.routineId = routine.getId(); + } + + public MemberRoutine toDomain() { + return MemberRoutine.builder() + .id(this.id) + .isAchieved(this.isAchieved) + .isAchievedToday(this.isAchievedToday) + .achievementCount(this.achievementCount) + .memberId(this.memberId) + .routineId(this.routineId) + .build(); + } + + public void update(MemberRoutine memberRoutine) { + this.isAchieved = memberRoutine.isAchieved(); + this.isAchievedToday = memberRoutine.isAchievedToday(); + this.achievementCount = memberRoutine.getAchievementCount(); + } + + public void restore() { + this.isDeleted = false; + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/MissionEntity.java b/src/main/java/com/soptie/server/persistence/entity/MissionEntity.java new file mode 100644 index 00000000..d92fbde1 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/MissionEntity.java @@ -0,0 +1,33 @@ +package com.soptie.server.persistence.entity; + +import com.soptie.server.domain.challenge.Mission; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +@Entity +@Table(name = "mission", schema = "softie") +public class MissionEntity extends BaseEntity { + @Column(nullable = false) + private String content; + @Column(nullable = false) + private String description; + @Column(nullable = false) + private String requiredTime; + @Column(nullable = false) + private String place; + @Column(nullable = false) + private long challengeId; + + public Mission toDomain() { + return Mission.builder() + .id(this.id) + .content(this.content) + .description(this.description) + .requiredTime(this.requiredTime) + .place(this.place) + .challengeId(this.challengeId) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/RoutineEntity.java b/src/main/java/com/soptie/server/persistence/entity/RoutineEntity.java new file mode 100644 index 00000000..1f1fbfb2 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/RoutineEntity.java @@ -0,0 +1,26 @@ +package com.soptie.server.persistence.entity; + +import com.soptie.server.domain.routine.Routine; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Getter; + +@Entity +@Getter +@Table(name = "routine", schema = "softie") +public class RoutineEntity extends BaseEntity { + @Column(nullable = false) + private String content; + @Column(nullable = false) + private long themeId; + + public Routine toDomain() { + return Routine.builder() + .id(this.id) + .content(this.content) + .themeId(this.themeId) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/entity/ThemeEntity.java b/src/main/java/com/soptie/server/persistence/entity/ThemeEntity.java new file mode 100644 index 00000000..4353bc1f --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/entity/ThemeEntity.java @@ -0,0 +1,32 @@ +package com.soptie.server.persistence.entity; + +import com.soptie.server.domain.theme.Theme; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +@Entity +@Table(name = "theme", schema = "softie") +public class ThemeEntity extends BaseEntity { + @Column(nullable = false) + private String name; + @Column(nullable = false) + private String comment; + @Column(nullable = false) + private String description; + @Column(nullable = false) + private int sequence; + private Long makerId; + + public Theme toDomain() { + return Theme.builder() + .id(this.id) + .name(this.name) + .comment(this.comment) + .description(this.description) + .sequence(this.sequence) + .makerId(this.makerId) + .build(); + } +} diff --git a/src/main/java/com/soptie/server/persistence/repository/ChallengeRepository.java b/src/main/java/com/soptie/server/persistence/repository/ChallengeRepository.java new file mode 100644 index 00000000..14f9521d --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/ChallengeRepository.java @@ -0,0 +1,11 @@ +package com.soptie.server.persistence.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.persistence.entity.ChallengeEntity; + +public interface ChallengeRepository extends JpaRepository { + List findByThemeId(long themeId); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/ConversationRepository.java b/src/main/java/com/soptie/server/persistence/repository/ConversationRepository.java new file mode 100644 index 00000000..8b4b32b9 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/ConversationRepository.java @@ -0,0 +1,8 @@ +package com.soptie.server.persistence.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.persistence.entity.ConversationEntity; + +public interface ConversationRepository extends JpaRepository { +} diff --git a/src/main/java/com/soptie/server/persistence/repository/DollRepository.java b/src/main/java/com/soptie/server/persistence/repository/DollRepository.java new file mode 100644 index 00000000..fa2b3db6 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/DollRepository.java @@ -0,0 +1,12 @@ +package com.soptie.server.persistence.repository; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.domain.doll.DollType; +import com.soptie.server.persistence.entity.DollEntity; + +public interface DollRepository extends JpaRepository { + Optional findByType(DollType type); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/MakerCustomRepository.java b/src/main/java/com/soptie/server/persistence/repository/MakerCustomRepository.java new file mode 100644 index 00000000..310a876a --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/MakerCustomRepository.java @@ -0,0 +1,9 @@ +package com.soptie.server.persistence.repository; + +import java.util.List; + +import com.soptie.server.api.controller.dto.response.maker.MakerThemeResponse; + +public interface MakerCustomRepository { + List findAllWithTheme(); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/MakerRepository.java b/src/main/java/com/soptie/server/persistence/repository/MakerRepository.java new file mode 100644 index 00000000..97b65c03 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/MakerRepository.java @@ -0,0 +1,8 @@ +package com.soptie.server.persistence.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.persistence.entity.MakerEntity; + +public interface MakerRepository extends JpaRepository { +} diff --git a/src/main/java/com/soptie/server/persistence/repository/MemberDollRepository.java b/src/main/java/com/soptie/server/persistence/repository/MemberDollRepository.java new file mode 100644 index 00000000..86390830 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/MemberDollRepository.java @@ -0,0 +1,15 @@ +package com.soptie.server.persistence.repository; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.persistence.entity.MemberDollEntity; + +public interface MemberDollRepository extends JpaRepository { + boolean existsByMemberId(long memberId); + + Optional findByMemberId(long memberId); + + void deleteByMemberId(long memberId); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/MemberMissionRepository.java b/src/main/java/com/soptie/server/persistence/repository/MemberMissionRepository.java new file mode 100644 index 00000000..b2fc705d --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/MemberMissionRepository.java @@ -0,0 +1,27 @@ +package com.soptie.server.persistence.repository; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; + +import com.soptie.server.persistence.entity.MemberMissionEntity; + +public interface MemberMissionRepository extends JpaRepository { + List findByMemberIdAndMissionIdIn(long memberId, List missionIds); + + @Modifying + @Query( + value = "DELETE FROM member_mission WHERE member_id = :memberId", + nativeQuery = true) + void deleteAllByMemberId(long memberId); + + Optional findByMemberId(long memberId); + + @Query( + value = "SELECT * FROM member_mission WHERE member_id = :memberId AND is_deleted = true", + nativeQuery = true) + List findDeletedByMemberId(long memberId); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/MemberRepository.java b/src/main/java/com/soptie/server/persistence/repository/MemberRepository.java new file mode 100644 index 00000000..9813355b --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/MemberRepository.java @@ -0,0 +1,14 @@ +package com.soptie.server.persistence.repository; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.domain.member.SocialType; +import com.soptie.server.persistence.entity.MemberEntity; + +public interface MemberRepository extends JpaRepository { + Optional findBySocialTypeAndSocialId(SocialType socialType, String socialId); + + Optional findByRefreshToken(String refreshToken); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/MemberRoutineRepository.java b/src/main/java/com/soptie/server/persistence/repository/MemberRoutineRepository.java new file mode 100644 index 00000000..a437d76c --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/MemberRoutineRepository.java @@ -0,0 +1,36 @@ +package com.soptie.server.persistence.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; + +import com.soptie.server.persistence.entity.MemberRoutineEntity; + +public interface MemberRoutineRepository extends JpaRepository { + @Query( + value = "SELECT * FROM member_routine WHERE member_id = :memberId AND is_deleted = true", + nativeQuery = true) + List findDeletedByMemberId(long memberId); + + @Query( + value = "SELECT * FROM member_routine WHERE is_achieved = :isAchieved AND is_deleted = true", + nativeQuery = true) + List findDeletedByIsAchieved(boolean isAchieved); + + List findByMemberId(long memberId); + + List findByIdIn(List ids); + + @SuppressWarnings("SpringDataMethodInconsistencyInspection") + List findByIsAchieved(boolean isAchieved); + + @Modifying + @Query( + value = "DELETE FROM member_routine WHERE member_id = :memberId", + nativeQuery = true) + void deleteAllByMemberId(long memberId); + + void deleteAllByIdIn(List ids); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/MissionRepository.java b/src/main/java/com/soptie/server/persistence/repository/MissionRepository.java new file mode 100644 index 00000000..bd4bc426 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/MissionRepository.java @@ -0,0 +1,11 @@ +package com.soptie.server.persistence.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.persistence.entity.MissionEntity; + +public interface MissionRepository extends JpaRepository { + List findByChallengeIdIn(List challengeIds); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/RoutineRepository.java b/src/main/java/com/soptie/server/persistence/repository/RoutineRepository.java new file mode 100644 index 00000000..39d4f27a --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/RoutineRepository.java @@ -0,0 +1,18 @@ +package com.soptie.server.persistence.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import com.soptie.server.persistence.entity.RoutineEntity; + +public interface RoutineRepository extends JpaRepository { + //TODO: 데이터베이스 내부 자체 처리 방법 찾아보기 + @Query( + value = "SELECT * FROM routine WHERE theme_id = :themeId ORDER BY content COLLATE \"ko_KR.utf8\" ASC", + nativeQuery = true) + List findByThemeIdOrderByContentAsc(long themeId); + + List findByIdIn(List ids); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/ThemeCustomRepository.java b/src/main/java/com/soptie/server/persistence/repository/ThemeCustomRepository.java new file mode 100644 index 00000000..0a370cfc --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/ThemeCustomRepository.java @@ -0,0 +1,9 @@ +package com.soptie.server.persistence.repository; + +import java.util.List; + +import com.soptie.server.api.controller.dto.response.maker.MakerThemeResponse; + +public interface ThemeCustomRepository { + List findAllWithMaker(); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/ThemeRepository.java b/src/main/java/com/soptie/server/persistence/repository/ThemeRepository.java new file mode 100644 index 00000000..54afbdd3 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/ThemeRepository.java @@ -0,0 +1,13 @@ +package com.soptie.server.persistence.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.soptie.server.persistence.entity.ThemeEntity; + +public interface ThemeRepository extends JpaRepository, ThemeCustomRepository { + List findByMakerIdIsNullOrderBySequenceAsc(); + + List findByIdIn(List ids); +} diff --git a/src/main/java/com/soptie/server/persistence/repository/ThemeRepositoryImpl.java b/src/main/java/com/soptie/server/persistence/repository/ThemeRepositoryImpl.java new file mode 100644 index 00000000..fcd060c3 --- /dev/null +++ b/src/main/java/com/soptie/server/persistence/repository/ThemeRepositoryImpl.java @@ -0,0 +1,30 @@ +package com.soptie.server.persistence.repository; + +import static com.soptie.server.persistence.entity.QMakerEntity.makerEntity; +import static com.soptie.server.persistence.entity.QThemeEntity.themeEntity; + +import java.util.List; + +import org.springframework.stereotype.Repository; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.soptie.server.api.controller.dto.response.maker.MakerThemeResponse; +import com.soptie.server.api.controller.dto.response.maker.QMakerThemeResponse; + +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class ThemeRepositoryImpl implements ThemeCustomRepository { + + private final JPAQueryFactory queryFactory; + + @Override + public List findAllWithMaker() { + return queryFactory.select(new QMakerThemeResponse(themeEntity, makerEntity)) + .from(themeEntity) + .innerJoin(makerEntity).on(themeEntity.makerId.eq(makerEntity.id)) + .fetchJoin() + .fetch(); + } +} diff --git a/src/main/java/com/soptie/server/routine/adapter/ChallengeFinder.java b/src/main/java/com/soptie/server/routine/adapter/ChallengeFinder.java deleted file mode 100644 index d5c91368..00000000 --- a/src/main/java/com/soptie/server/routine/adapter/ChallengeFinder.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.soptie.server.routine.adapter; - -import static com.soptie.server.routine.message.RoutineErrorCode.INVALID_ROUTINE; - -import java.util.List; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.routine.entity.Challenge; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.exception.RoutineException; -import com.soptie.server.routine.repository.ChallengeRepository; -import com.soptie.server.routine.service.vo.ChallengeVO; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class ChallengeFinder { - - private final ChallengeRepository challengeRepository; - - public Challenge findById(long id) { - return challengeRepository.findById(id) - .orElseThrow(() -> new RoutineException(INVALID_ROUTINE)); - } - - public List findByRoutine(Routine routine) { - return challengeRepository.findByRoutine(routine).stream().map(ChallengeVO::from).toList(); - } -} diff --git a/src/main/java/com/soptie/server/routine/adapter/RoutineFinder.java b/src/main/java/com/soptie/server/routine/adapter/RoutineFinder.java deleted file mode 100644 index f6ce4ab8..00000000 --- a/src/main/java/com/soptie/server/routine/adapter/RoutineFinder.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.soptie.server.routine.adapter; - -import static com.soptie.server.routine.message.RoutineErrorCode.*; - -import java.util.List; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; -import com.soptie.server.routine.exception.RoutineException; -import com.soptie.server.routine.repository.RoutineRepository; -import com.soptie.server.routine.service.vo.RoutineVO; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class RoutineFinder { - - private final RoutineRepository routineRepository; - - public List findAllByTypeAndThemeIds(RoutineType type, List themeIds) { - return routineRepository.findByTypeAndThemeIds(type, themeIds).stream().map(RoutineVO::from).toList(); - } - - public List findAllNotInMemberByTypeAndThemeId(long memberId, RoutineType type, long themeId) { - return routineRepository.findByTypeAndThemeAndNotMember(memberId, type, themeId) - .stream().map(RoutineVO::from).toList(); - } - - public Routine findById(long id) { - return routineRepository.findById(id) - .orElseThrow(() -> new RoutineException(INVALID_ROUTINE)); - } - - public List findDailyByIds(List ids) { - return routineRepository.findByIdsAndType(ids, RoutineType.DAILY); - } - - public List findChallengeRoutinesByTheme(Long themeId) { - return routineRepository.findByTypeAndThemeId(RoutineType.CHALLENGE, themeId); - } - - public List findAllByTypeAndThemeId(RoutineType type, Long themeId) { - return routineRepository.findByTypeAndThemeId(type, themeId); - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v1/DailyRoutineController.java b/src/main/java/com/soptie/server/routine/controller/v1/DailyRoutineController.java deleted file mode 100644 index 8dc76a64..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v1/DailyRoutineController.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.soptie.server.routine.controller.v1; - -import java.security.Principal; -import java.util.List; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.routine.controller.v1.docs.DailyRoutineControllerDocs; -import com.soptie.server.routine.controller.v1.dto.response.DailyRoutineListAcquireResponse; -import com.soptie.server.routine.message.RoutineSuccessMessage; -import com.soptie.server.routine.service.RoutineService; -import com.soptie.server.theme.service.ThemeService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/routines/daily") -public class DailyRoutineController implements DailyRoutineControllerDocs { - - private final RoutineService routineService; - private final ThemeService themeService; - - @GetMapping - public ResponseEntity> acquireAllByThemes( - @RequestParam List themes - ) { - val response = routineService.acquireAllInDailyByThemeIds(themes); - return ResponseEntity.ok(SuccessResponse.success( - RoutineSuccessMessage.SUCCESS_GET_ROUTINE.getMessage(), - DailyRoutineListAcquireResponse.from(response))); - } - - @GetMapping("/theme/{themeId}") - public ResponseEntity> acquireAllByTheme( - Principal principal, - @PathVariable long themeId - ) { - val memberId = Long.parseLong(principal.getName()); - val themeResponse = themeService.acquireById(themeId); - val routinesResponse = routineService.acquireAllInDailyNotInMemberByThemeId(memberId, themeId); - return ResponseEntity.ok(SuccessResponse.success( - RoutineSuccessMessage.SUCCESS_GET_ROUTINE.getMessage(), - DailyRoutineListAcquireResponse.from(themeResponse, routinesResponse))); - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v1/HappinessRoutineController.java b/src/main/java/com/soptie/server/routine/controller/v1/HappinessRoutineController.java deleted file mode 100644 index 80795c8d..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v1/HappinessRoutineController.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.soptie.server.routine.controller.v1; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.routine.controller.v1.docs.HappinessRoutineControllerDocs; -import com.soptie.server.routine.controller.v1.dto.response.HappinessRoutineListAcquireResponse; -import com.soptie.server.routine.controller.v1.dto.response.HappinessSubRoutineListAcquireResponse; -import com.soptie.server.routine.message.RoutineSuccessMessage; -import com.soptie.server.routine.service.RoutineService; -import com.soptie.server.routine.service.dto.request.HappinessSubRoutineListGetServiceRequest; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/routines/happiness") -public class HappinessRoutineController implements HappinessRoutineControllerDocs { - - private final RoutineService routineService; - - @GetMapping - public ResponseEntity> acquireAllByTheme( - @RequestParam(required = false) Long themeId - ) { - val response = routineService.acquireAllInHappinessByThemeId(themeId); - return ResponseEntity.ok(SuccessResponse.success( - RoutineSuccessMessage.SUCCESS_GET_HAPPINESS_ROUTINE.getMessage(), - HappinessRoutineListAcquireResponse.from(response))); - } - - @GetMapping("/routine/{routineId}") - public ResponseEntity> acquireAllInSubByRoutine( - @PathVariable long routineId - ) { - val response = routineService.getHappinessSubRoutines(HappinessSubRoutineListGetServiceRequest.of(routineId)); - return ResponseEntity.ok(SuccessResponse.success( - RoutineSuccessMessage.SUCCESS_GET_HAPPINESS_SUB_ROUTINES.getMessage(), - HappinessSubRoutineListAcquireResponse.of(response))); - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v1/docs/HappinessRoutineControllerDocs.java b/src/main/java/com/soptie/server/routine/controller/v1/docs/HappinessRoutineControllerDocs.java deleted file mode 100644 index 43380c8b..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v1/docs/HappinessRoutineControllerDocs.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.soptie.server.routine.controller.v1.docs; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; - -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.routine.controller.v1.dto.response.HappinessRoutineListAcquireResponse; -import com.soptie.server.routine.controller.v1.dto.response.HappinessSubRoutineListAcquireResponse; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "happiness routines", description = "행복 루틴 API") -public interface HappinessRoutineControllerDocs { - - @Operation( - summary = "테마 목록별 행복 루틴 목록 조회", - description = "테마 목록 중 해당되는 행복 루틴 목록을 조회한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity> acquireAllByTheme( - @Parameter( - name = "themeId", - description = "조회할 행복 루틴 테마 id", - in = ParameterIn.QUERY, - example = "1" - ) @RequestParam(required = false) Long themeId - ); - - @Operation( - summary = "루틴 별 행복 서브 루틴 내용 조회", - description = "루틴에 해당되는 행복 서브 루틴 내용을 조회한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity> acquireAllInSubByRoutine( - @Parameter( - name = "routineId", - description = "조회할 서브 행복 루틴 id", - in = ParameterIn.PATH, - example = "1" - ) @PathVariable long routineId - ); -} diff --git a/src/main/java/com/soptie/server/routine/controller/v1/dto/response/DailyRoutineListAcquireResponse.java b/src/main/java/com/soptie/server/routine/controller/v1/dto/response/DailyRoutineListAcquireResponse.java deleted file mode 100644 index fd0a372a..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v1/dto/response/DailyRoutineListAcquireResponse.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.soptie.server.routine.controller.v1.dto.response; - -import java.util.List; - -import com.soptie.server.routine.service.vo.RoutineVO; -import com.soptie.server.theme.service.vo.ThemeVO; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record DailyRoutineListAcquireResponse( - String backgroundImageUrl, - @NonNull List routines -) { - - public static DailyRoutineListAcquireResponse from(ThemeVO theme, List routines) { - return DailyRoutineListAcquireResponse.builder() - .backgroundImageUrl(theme.imageLinks().backgroundImageUrl()) - .routines(routines.stream().map(DailyRoutineResponse::from).toList()) - .build(); - } - - public static DailyRoutineListAcquireResponse from(List routines) { - return DailyRoutineListAcquireResponse.builder() - .routines(routines.stream().map(DailyRoutineResponse::from).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record DailyRoutineResponse( - long routineId, - @NonNull String content - ) { - - private static DailyRoutineResponse from(RoutineVO routine) { - return DailyRoutineResponse.builder() - .routineId(routine.routineId()) - .content(routine.content()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v1/dto/response/HappinessRoutineListAcquireResponse.java b/src/main/java/com/soptie/server/routine/controller/v1/dto/response/HappinessRoutineListAcquireResponse.java deleted file mode 100644 index e625e746..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v1/dto/response/HappinessRoutineListAcquireResponse.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.soptie.server.routine.controller.v1.dto.response; - -import java.util.List; -import java.util.Objects; - -import com.soptie.server.routine.entity.Routine; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record HappinessRoutineListAcquireResponse( - List routines -) { - - public static HappinessRoutineListAcquireResponse from(List routines) { - return HappinessRoutineListAcquireResponse.builder() - .routines(routines.stream().map(HappinessRoutineResponse::from).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record HappinessRoutineResponse( - long routineId, - @NonNull String name, - @NonNull String nameColor, - @NonNull String title, - @NonNull String iconImageUrl - ) { - - private static HappinessRoutineResponse from(Routine routine) { - return HappinessRoutineResponse.builder() - .routineId(routine.getId()) - .name(Objects.nonNull(routine.getTheme()) ? routine.getTheme().getName() : "알 수 없는 테마") - .nameColor(Objects.nonNull(routine.getTheme()) ? routine.getTheme().getColor() : "#FFFFFF") - .title(routine.getContent()) - .iconImageUrl(routine.getTheme() != null ? routine.getTheme().getImageLinks().getIconImageUrl() : "") - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v1/dto/response/HappinessSubRoutineListAcquireResponse.java b/src/main/java/com/soptie/server/routine/controller/v1/dto/response/HappinessSubRoutineListAcquireResponse.java deleted file mode 100644 index 80cffa9c..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v1/dto/response/HappinessSubRoutineListAcquireResponse.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.soptie.server.routine.controller.v1.dto.response; - -import java.util.List; - -import com.soptie.server.routine.service.dto.response.HappinessSubRoutineListGetServiceResponse; -import com.soptie.server.routine.service.dto.response.HappinessSubRoutineListGetServiceResponse.HappinessSubRoutineServiceResponse; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record HappinessSubRoutineListAcquireResponse( - @NonNull String title, - @NonNull String name, - @NonNull String nameColor, - @NonNull String iconImageUrl, - @NonNull String contentImageUrl, - @NonNull List subRoutines -) { - - public static HappinessSubRoutineListAcquireResponse of(HappinessSubRoutineListGetServiceResponse response) { - return HappinessSubRoutineListAcquireResponse.builder() - .title(response.routineContent()) - .name(response.themeName()) - .nameColor(response.themeColor()) - .iconImageUrl(response.iconImageUrl()) - .contentImageUrl(response.backgroundImageUrl()) - .subRoutines(response.challenges().stream().map(HappinessSubRoutineResponse::of).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record HappinessSubRoutineResponse( - long subRoutineId, - @NonNull String content, - @NonNull String detailContent, - @NonNull String timeTaken, - @NonNull String place - ) { - - private static HappinessSubRoutineResponse of(HappinessSubRoutineServiceResponse response) { - return HappinessSubRoutineResponse.builder() - .subRoutineId(response.challengeId()) - .content(response.content()) - .detailContent(response.description()) - .timeTaken(response.requiredTime()) - .place(response.place()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v2/ChallengeRoutineControllerV2.java b/src/main/java/com/soptie/server/routine/controller/v2/ChallengeRoutineControllerV2.java deleted file mode 100644 index e6959581..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v2/ChallengeRoutineControllerV2.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.soptie.server.routine.controller.v2; - -import java.security.Principal; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.routine.controller.v2.docs.ChallengeRoutineControllerV2Docs; -import com.soptie.server.routine.controller.v2.dto.response.ChallengeRoutineListAcquireResponseV2; -import com.soptie.server.routine.message.RoutineSuccessMessage; -import com.soptie.server.routine.service.RoutineService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v2/routines/challenge") -public class ChallengeRoutineControllerV2 implements ChallengeRoutineControllerV2Docs { - - private final RoutineService routineService; - - @GetMapping - public ResponseEntity> acquireAllByTheme( - Principal principal, - @RequestParam long themeId - ) { - val memberId = Long.parseLong(principal.getName()); - val response = routineService.acquireAllInChallengeWithThemeId(memberId, themeId); - return ResponseEntity.ok(SuccessResponse.success( - RoutineSuccessMessage.SUCCESS_GET_CHALLENGE_ROUTINE.getMessage(), - ChallengeRoutineListAcquireResponseV2.from(response))); - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v2/DailyRoutineControllerV2.java b/src/main/java/com/soptie/server/routine/controller/v2/DailyRoutineControllerV2.java deleted file mode 100644 index 3c271a55..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v2/DailyRoutineControllerV2.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.soptie.server.routine.controller.v2; - -import java.security.Principal; -import java.util.LinkedHashSet; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.routine.controller.v2.docs.DailyRoutineControllerV2Docs; -import com.soptie.server.routine.controller.v2.dto.response.DailyRoutineListAcquireResponseV2; -import com.soptie.server.routine.controller.v2.dto.response.DailyRoutinesAcquireResponseV2; -import com.soptie.server.routine.message.RoutineSuccessMessage; -import com.soptie.server.routine.service.RoutineService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v2/routines/daily") -public class DailyRoutineControllerV2 implements DailyRoutineControllerV2Docs { - - private final RoutineService routineService; - - @GetMapping - public ResponseEntity> acquireAllByThemes( - @RequestParam LinkedHashSet themeIds - ) { - val response = routineService.acquireAllInDailyWithThemeId(themeIds); - return ResponseEntity.ok(SuccessResponse.success( - RoutineSuccessMessage.SUCCESS_GET_ROUTINE.getMessage(), - DailyRoutineListAcquireResponseV2.from(response))); - } - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/theme/{themeId}") - public SuccessResponse acquireAllByThemeAndMember( - Principal principal, - @PathVariable long themeId - ) { - val memberId = Long.parseLong(principal.getName()); - val response = routineService.acquireAllInDailyByThemeAndMember(memberId, themeId); - return SuccessResponse.success( - RoutineSuccessMessage.SUCCESS_GET_ROUTINE.getMessage(), - DailyRoutinesAcquireResponseV2.from(response)); - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v2/docs/DailyRoutineControllerV2Docs.java b/src/main/java/com/soptie/server/routine/controller/v2/docs/DailyRoutineControllerV2Docs.java deleted file mode 100644 index 80056734..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v2/docs/DailyRoutineControllerV2Docs.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.soptie.server.routine.controller.v2.docs; - -import java.security.Principal; -import java.util.LinkedHashSet; - -import org.springframework.http.ResponseEntity; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.routine.controller.v2.dto.response.DailyRoutineListAcquireResponseV2; -import com.soptie.server.routine.controller.v2.dto.response.DailyRoutinesAcquireResponseV2; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "DailyRoutineApiV2", description = "데일리 루틴 API (version2)") -public interface DailyRoutineControllerV2Docs { - - @Operation( - summary = "데일리 루틴 목록 조회", - description = "특정 테마 id 목록에 속하는 데일리 루틴 목록을 조회합니다." - ) - @ApiResponses(value = { - @ApiResponse( - responseCode = "200", - description = "OK Success", - content = @Content(schema = @Schema(implementation = DailyRoutineListAcquireResponseV2.class)))}) - ResponseEntity> acquireAllByThemes( - @Parameter( - name = "themeIds", - description = "조회할 테마 id 목록", - required = true, - in = ParameterIn.QUERY - ) LinkedHashSet themeIds - ); - - @Operation( - summary = "데일리 루틴 목록 조회", - description = "특정 테마에 속하는 데일리 루틴 목록을 조회합니다. 회원이 가진 유무를 함께 확인할 수 있습니다." - ) - @ApiResponses(value = { - @ApiResponse( - responseCode = "200", - description = "OK Success", - content = @Content(schema = @Schema(implementation = DailyRoutinesAcquireResponseV2.class)))}) - SuccessResponse acquireAllByThemeAndMember( - @Parameter(hidden = true) Principal principal, - @Parameter( - name = "themeId", - description = "조회하려는 루틴의 테마 id", - required = true, - in = ParameterIn.PATH - ) long themeId - ); -} diff --git a/src/main/java/com/soptie/server/routine/controller/v2/dto/response/ChallengeRoutineListAcquireResponseV2.java b/src/main/java/com/soptie/server/routine/controller/v2/dto/response/ChallengeRoutineListAcquireResponseV2.java deleted file mode 100644 index f41e0572..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v2/dto/response/ChallengeRoutineListAcquireResponseV2.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.soptie.server.routine.controller.v2.dto.response; - -import java.util.List; -import java.util.Map; - -import com.soptie.server.routine.service.dto.response.ChallengeRoutineListAcquireServiceResponse; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record ChallengeRoutineListAcquireResponseV2( - @NonNull List routines -) { - - public static ChallengeRoutineListAcquireResponseV2 from( - Map challengesMap - ) { - return ChallengeRoutineListAcquireResponseV2.builder() - .routines(challengesMap.keySet() - .stream() - .map(key -> RoutineResponse.from(key, challengesMap.get(key))) - .toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record RoutineResponse( - @NonNull String title, - @NonNull List challenges - ) { - - private static RoutineResponse from(String title, ChallengeRoutineListAcquireServiceResponse challenges) { - return RoutineResponse.builder() - .title(title) - .challenges(challenges.challenges().stream().map(ChallengeResponse::from).toList()) - .build(); - } - } - - @Builder(access = AccessLevel.PRIVATE) - private record ChallengeResponse( - long challengeId, - @NonNull String content, - @NonNull String description, - @NonNull String requiredTime, - @NonNull String place, - boolean hasRoutine - ) { - - private static ChallengeResponse from( - ChallengeRoutineListAcquireServiceResponse.ChallengeRoutineAcquireResponse challenge) { - return ChallengeResponse.builder() - .challengeId(challenge.challenge().challengeId()) - .content(challenge.challenge().content()) - .description(challenge.challenge().description()) - .requiredTime(challenge.challenge().requiredTime()) - .place(challenge.challenge().place()) - .hasRoutine(challenge.hasRoutine()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v2/dto/response/DailyRoutineListAcquireResponseV2.java b/src/main/java/com/soptie/server/routine/controller/v2/dto/response/DailyRoutineListAcquireResponseV2.java deleted file mode 100644 index 2a11a7d9..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v2/dto/response/DailyRoutineListAcquireResponseV2.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.soptie.server.routine.controller.v2.dto.response; - -import java.util.List; -import java.util.Map; - -import com.soptie.server.routine.entity.Routine; - -import jakarta.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.Builder; - -@Builder(access = AccessLevel.PRIVATE) -public record DailyRoutineListAcquireResponseV2( - List themes -) { - - public static DailyRoutineListAcquireResponseV2 from(Map> routinesMap) { - return DailyRoutineListAcquireResponseV2.builder() - .themes(routinesMap.keySet().stream().map(key -> ThemeResponse.from(key, routinesMap.get(key))).toList()) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record ThemeResponse( - long themeId, - List routines - ) { - - private static ThemeResponse from(long themeId, List routines) { - return ThemeResponse.builder() - .themeId(themeId) - .routines(routines.stream().map(RoutineResponse::from).toList()) - .build(); - } - } - - @Builder(access = AccessLevel.PRIVATE) - private record RoutineResponse( - long routineId, - @NotNull String content - ) { - - private static RoutineResponse from(Routine routine) { - return RoutineResponse.builder() - .routineId(routine.getId()) - .content(routine.getContent()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/routine/controller/v2/dto/response/DailyRoutinesAcquireResponseV2.java b/src/main/java/com/soptie/server/routine/controller/v2/dto/response/DailyRoutinesAcquireResponseV2.java deleted file mode 100644 index 0c3c6508..00000000 --- a/src/main/java/com/soptie/server/routine/controller/v2/dto/response/DailyRoutinesAcquireResponseV2.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.soptie.server.routine.controller.v2.dto.response; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import com.soptie.server.routine.entity.Routine; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.val; - -@Builder(access = AccessLevel.PRIVATE) -public record DailyRoutinesAcquireResponseV2( - @Schema(description = "조회하려는 루틴 목록") - @NotNull - List routines -) { - - public static DailyRoutinesAcquireResponseV2 from(Map> routineToMember) { - val routines = new ArrayList(); - for (val key : routineToMember.keySet()) { - routines.addAll(routineToMember.get(key).stream() - .map(routine -> DailyRoutineResponse.of(routine, key)) - .toList()); - } - return DailyRoutinesAcquireResponseV2.builder() - .routines(routines) - .build(); - } - - @Builder(access = AccessLevel.PRIVATE) - private record DailyRoutineResponse( - @Schema(description = "루틴 id") - long id, - @Schema(description = "루틴 내용") - @NotNull - String content, - @Schema(description = "회원이 가지고 있는 루틴 유무") - boolean existedInMember - ) { - - private static DailyRoutineResponse of(Routine routine, boolean existedInMember) { - return DailyRoutineResponse.builder() - .id(routine.getId()) - .content(routine.getContent()) - .existedInMember(existedInMember) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/routine/entity/Challenge.java b/src/main/java/com/soptie/server/routine/entity/Challenge.java deleted file mode 100644 index 778d749e..00000000 --- a/src/main/java/com/soptie/server/routine/entity/Challenge.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.soptie.server.routine.entity; - -import static jakarta.persistence.FetchType.*; -import static jakarta.persistence.GenerationType.*; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -@Getter -public class Challenge { - - @Id - @GeneratedValue(strategy = IDENTITY) - @Column(name = "challenge_id") - private Long id; - - private String content; - - private String description; - - private String requiredTime; - - private String place; - - @ManyToOne(fetch = LAZY) - @JoinColumn(name = "routine_id") - private Routine routine; - - public Challenge(Long id, String content, String description, String requiredTime, String place, Routine routine) { - this.id = id; - this.content = content; - this.description = description; - this.requiredTime = requiredTime; - this.place = place; - this.routine = routine; - } -} diff --git a/src/main/java/com/soptie/server/routine/entity/Routine.java b/src/main/java/com/soptie/server/routine/entity/Routine.java deleted file mode 100644 index 464d1218..00000000 --- a/src/main/java/com/soptie/server/routine/entity/Routine.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.soptie.server.routine.entity; - -import static jakarta.persistence.EnumType.*; -import static jakarta.persistence.FetchType.*; -import static jakarta.persistence.GenerationType.*; - -import com.soptie.server.theme.entity.Theme; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.validation.constraints.NotNull; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -@Getter -public class Routine { - - @Id - @GeneratedValue(strategy = IDENTITY) - @Column(name = "routine_id") - private Long id; - - @NotNull - private String content; - - @Enumerated(value = STRING) - private RoutineType type; - - @ManyToOne(fetch = LAZY) - @JoinColumn(name = "theme_id") - private Theme theme; - - public Routine(Long id, String content, RoutineType type, Theme theme) { - this.id = id; - this.content = content; - this.type = type; - this.theme = theme; - } -} diff --git a/src/main/java/com/soptie/server/routine/entity/RoutineType.java b/src/main/java/com/soptie/server/routine/entity/RoutineType.java deleted file mode 100644 index 85de1923..00000000 --- a/src/main/java/com/soptie/server/routine/entity/RoutineType.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.routine.entity; - -import static lombok.AccessLevel.*; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor(access = PROTECTED) -public enum RoutineType { - - DAILY("데일리"), - CHALLENGE("도전"); - - private final String name; -} diff --git a/src/main/java/com/soptie/server/routine/exception/RoutineException.java b/src/main/java/com/soptie/server/routine/exception/RoutineException.java deleted file mode 100644 index 534df359..00000000 --- a/src/main/java/com/soptie/server/routine/exception/RoutineException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.routine.exception; - -import com.soptie.server.routine.message.RoutineErrorCode; - -import lombok.Getter; - -@Getter -public class RoutineException extends RuntimeException { - - private final RoutineErrorCode errorCode; - - public RoutineException(RoutineErrorCode errorCode) { - super("[RoutineException] : " + errorCode.getMessage()); - this.errorCode = errorCode; - } -} diff --git a/src/main/java/com/soptie/server/routine/message/RoutineErrorCode.java b/src/main/java/com/soptie/server/routine/message/RoutineErrorCode.java deleted file mode 100644 index b103efdf..00000000 --- a/src/main/java/com/soptie/server/routine/message/RoutineErrorCode.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.soptie.server.routine.message; - -import static org.springframework.http.HttpStatus.*; - -import org.springframework.http.HttpStatus; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public enum RoutineErrorCode { - - /* 400 BAD_REQUEST : 잘못된 요청 */ - CANNOT_ADD_MEMBER_ROUTINE(BAD_REQUEST, "더 이상 루틴을 추가할 수 없는 회원입니다."), - - /* 404 NOT_FOUND : 자원을 찾을 수 없음 */ - INVALID_ROUTINE(NOT_FOUND, "유효하지 않은 루틴입니다."), - - /* 409 CONFLICT : 중복된 데이터 존재 */ - DUPLICATED_ROUTINE(CONFLICT, "이미 추가한 루틴입니다."); - - private final HttpStatus httpStatus; - private final String message; -} diff --git a/src/main/java/com/soptie/server/routine/message/RoutineSuccessMessage.java b/src/main/java/com/soptie/server/routine/message/RoutineSuccessMessage.java deleted file mode 100644 index ee2436f8..00000000 --- a/src/main/java/com/soptie/server/routine/message/RoutineSuccessMessage.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.routine.message; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum RoutineSuccessMessage { - - SUCCESS_GET_ROUTINE("데일리 루틴 조회 성공"), - SUCCESS_GET_HAPPINESS_ROUTINE("행복 루틴 조회 성공"), - SUCCESS_GET_CHALLENGE_ROUTINE("도전 루틴 조회 성공"), - SUCCESS_GET_HAPPINESS_SUB_ROUTINES("행복 루틴 별 서브 루틴 리스트 조회 성공"); - - private final String message; -} diff --git a/src/main/java/com/soptie/server/routine/repository/ChallengeRepository.java b/src/main/java/com/soptie/server/routine/repository/ChallengeRepository.java deleted file mode 100644 index ff37e8c5..00000000 --- a/src/main/java/com/soptie/server/routine/repository/ChallengeRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.soptie.server.routine.repository; - -import java.util.List; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.routine.entity.Challenge; -import com.soptie.server.routine.entity.Routine; - -public interface ChallengeRepository extends JpaRepository { - List findByRoutine(Routine routine); -} diff --git a/src/main/java/com/soptie/server/routine/repository/RoutineCustomRepository.java b/src/main/java/com/soptie/server/routine/repository/RoutineCustomRepository.java deleted file mode 100644 index 7aabf649..00000000 --- a/src/main/java/com/soptie/server/routine/repository/RoutineCustomRepository.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.routine.repository; - -import java.util.List; - -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; - -public interface RoutineCustomRepository { - List findByTypeAndThemeIds(RoutineType type, List themeIds); - - List findByTypeAndThemeAndNotMember(long memberId, RoutineType type, long themeId); - - List findByTypeAndThemeId(RoutineType type, Long themeId); - - List findByIdsAndType(List ids, RoutineType type); -} diff --git a/src/main/java/com/soptie/server/routine/repository/RoutineRepository.java b/src/main/java/com/soptie/server/routine/repository/RoutineRepository.java deleted file mode 100644 index 6e82f10f..00000000 --- a/src/main/java/com/soptie/server/routine/repository/RoutineRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soptie.server.routine.repository; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.routine.entity.Routine; - -public interface RoutineRepository extends JpaRepository, RoutineCustomRepository { -} diff --git a/src/main/java/com/soptie/server/routine/repository/RoutineRepositoryImpl.java b/src/main/java/com/soptie/server/routine/repository/RoutineRepositoryImpl.java deleted file mode 100644 index 6981c8b3..00000000 --- a/src/main/java/com/soptie/server/routine/repository/RoutineRepositoryImpl.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.soptie.server.routine.repository; - -import static com.soptie.server.memberroutine.entity.QMemberRoutine.*; -import static com.soptie.server.routine.entity.QRoutine.*; -import static java.util.Objects.*; - -import java.util.List; - -import org.springframework.stereotype.Repository; - -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.impl.JPAQueryFactory; -import com.soptie.server.common.support.ExpressionGenerator; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; - -import lombok.RequiredArgsConstructor; - -@Repository -@RequiredArgsConstructor -public class RoutineRepositoryImpl implements RoutineCustomRepository { - - private final JPAQueryFactory queryFactory; - - public List findByTypeAndThemeIds(RoutineType type, List themeIds) { - return queryFactory - .selectFrom(routine) - .where( - routine.type.eq(type), - routine.theme.id.in(themeIds) - ) - .orderBy(ExpressionGenerator.getFirstLetter(routine.content).asc()) - .fetch(); - } - - public List findByTypeAndThemeAndNotMember(long memberId, RoutineType type, long themeId) { - return queryFactory - .selectFrom(routine) - .leftJoin(memberRoutine) - .on( - routine.id.eq(memberRoutine.routineId), - memberRoutine.type.eq(type), - memberRoutine.member.id.eq(memberId) - ) - .where( - memberRoutine.isNull(), - routine.type.eq(type), - routine.theme.id.eq(themeId) - ) - .orderBy(ExpressionGenerator.getFirstLetter(routine.content).asc()) - .fetch(); - } - - public List findByTypeAndThemeId(RoutineType type, Long themeId) { - return queryFactory - .selectFrom(routine) - .where( - routine.type.eq(type), - themeEq(themeId) - ) - .orderBy(ExpressionGenerator.getFirstLetter(routine.content).asc()) - .fetch(); - } - - @Override - public List findByIdsAndType(List ids, RoutineType type) { - return queryFactory - .selectFrom(routine) - .where( - routine.id.in(ids), - routine.type.eq(type) - ) - .fetch(); - } - - private BooleanExpression themeEq(Long themeId) { - return (isNull(themeId) || themeId == 0L) ? null : routine.theme.id.eq(themeId); - } -} diff --git a/src/main/java/com/soptie/server/routine/service/RoutineService.java b/src/main/java/com/soptie/server/routine/service/RoutineService.java deleted file mode 100644 index 19afb813..00000000 --- a/src/main/java/com/soptie/server/routine/service/RoutineService.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.soptie.server.routine.service; - -import static com.soptie.server.common.config.ValueConfig.*; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.adapter.MemberRoutineFinder; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.memberroutine.repository.dto.MemberChallengeResponse; -import com.soptie.server.routine.adapter.ChallengeFinder; -import com.soptie.server.routine.adapter.RoutineFinder; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; -import com.soptie.server.routine.service.dto.request.HappinessSubRoutineListGetServiceRequest; -import com.soptie.server.routine.service.dto.response.ChallengeRoutineListAcquireServiceResponse; -import com.soptie.server.routine.service.dto.response.HappinessSubRoutineListGetServiceResponse; -import com.soptie.server.routine.service.vo.RoutineVO; -import com.soptie.server.theme.adapter.ThemeFinder; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class RoutineService { - - private final RoutineFinder routineFinder; - private final ChallengeFinder challengeFinder; - private final MemberRoutineFinder memberRoutineFinder; - private final ThemeFinder themeFinder; - private final MemberFinder memberFinder; - - public List acquireAllInDailyByThemeIds(List themeIds) { - return routineFinder.findAllByTypeAndThemeIds(RoutineType.DAILY, themeIds); - } - - public List acquireAllInDailyNotInMemberByThemeId(long memberId, long themeId) { - return routineFinder.findAllNotInMemberByTypeAndThemeId(memberId, RoutineType.DAILY, themeId); - } - - public List acquireAllInHappinessByThemeId(Long themeId) { - return routineFinder.findAllByTypeAndThemeId(RoutineType.CHALLENGE, themeId); - } - - public HappinessSubRoutineListGetServiceResponse getHappinessSubRoutines( - HappinessSubRoutineListGetServiceRequest request - ) { - val routine = routineFinder.findById(request.routineId()); - val subRoutines = challengeFinder.findByRoutine(routine); - return HappinessSubRoutineListGetServiceResponse.of(routine, subRoutines); - } - - public Map> acquireAllInDailyWithThemeId(Set themeIds) { - val themeToRoutine = new LinkedHashMap>(); - for (val themeId : themeIds) { - val routines = routineFinder.findAllByTypeAndThemeId(RoutineType.DAILY, themeId); - themeToRoutine.put(themeId, routines); - } - return themeToRoutine; - } - - public Map acquireAllInChallengeWithThemeId( - long memberId, - long themeId - ) { - themeFinder.isExistById(themeId); - val member = memberFinder.findById(memberId); - val challengeIdByMember = getChallengeIdByMember(member); - val challengeRoutinesByTheme = routineFinder.findChallengeRoutinesByTheme(themeId); - val themeToChallenge = new LinkedHashMap(); - for (val routine : challengeRoutinesByTheme) { - val challenges = challengeFinder.findByRoutine(routine); - themeToChallenge.put(routine.getContent(), - ChallengeRoutineListAcquireServiceResponse.of(challenges, challengeIdByMember)); - } - return themeToChallenge; - } - - public Map> acquireAllInDailyByThemeAndMember(long memberId, long themeId) { - val routines = routineFinder.findAllByTypeAndThemeId(RoutineType.DAILY, themeId); - val member = memberFinder.findById(memberId); - val memberRoutineIds = memberRoutineFinder.findAllByMemberAndType(member, RoutineType.DAILY).stream() - .map(MemberRoutine::getRoutineId) - .toList(); - return getRoutineToMember(routines, memberRoutineIds); - } - - private Map> getRoutineToMember(List routines, List memberRoutineIds) { - val routineToMember = new HashMap>(); - routineToMember.put(true, new ArrayList<>()); - routineToMember.put(false, new ArrayList<>()); - for (val routine : routines) { - val isMemberRoutine = memberRoutineIds.contains(routine.getId()); - routineToMember.get(isMemberRoutine).add(routine); - } - return routineToMember; - } - - private long getChallengeIdByMember(Member member) { - val challengeByMember = memberRoutineFinder.findChallengeByMember(member); - return challengeByMember.map(MemberChallengeResponse::challengeId).orElse(MEMBER_HAS_NOT_CHALLENGE); - } -} diff --git a/src/main/java/com/soptie/server/routine/service/dto/request/HappinessSubRoutineListGetServiceRequest.java b/src/main/java/com/soptie/server/routine/service/dto/request/HappinessSubRoutineListGetServiceRequest.java deleted file mode 100644 index 496e8dac..00000000 --- a/src/main/java/com/soptie/server/routine/service/dto/request/HappinessSubRoutineListGetServiceRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.soptie.server.routine.service.dto.request; - -import static lombok.AccessLevel.PRIVATE; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record HappinessSubRoutineListGetServiceRequest( - long routineId -) { - - public static HappinessSubRoutineListGetServiceRequest of(long routineId) { - return HappinessSubRoutineListGetServiceRequest.builder() - .routineId(routineId) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/routine/service/dto/response/ChallengeRoutineListAcquireServiceResponse.java b/src/main/java/com/soptie/server/routine/service/dto/response/ChallengeRoutineListAcquireServiceResponse.java deleted file mode 100644 index d29defda..00000000 --- a/src/main/java/com/soptie/server/routine/service/dto/response/ChallengeRoutineListAcquireServiceResponse.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.soptie.server.routine.service.dto.response; - -import static lombok.AccessLevel.PRIVATE; - -import java.util.List; - -import com.soptie.server.routine.service.vo.ChallengeVO; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record ChallengeRoutineListAcquireServiceResponse( - @NonNull List challenges -) { - - public static ChallengeRoutineListAcquireServiceResponse of(List challenges, long challengeId) { - return ChallengeRoutineListAcquireServiceResponse.builder() - .challenges(challenges.stream() - .map(challenge -> ChallengeRoutineAcquireResponse.of(challenge, challengeId)) - .toList()) - .build(); - } - - @Builder(access = PRIVATE) - public record ChallengeRoutineAcquireResponse( - ChallengeVO challenge, - boolean hasRoutine - ) { - - public static ChallengeRoutineAcquireResponse of(ChallengeVO challenge, long challengeId) { - return ChallengeRoutineAcquireResponse.builder() - .challenge(challenge) - .hasRoutine(challenge.challengeId() == challengeId) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/routine/service/dto/response/HappinessSubRoutineListGetServiceResponse.java b/src/main/java/com/soptie/server/routine/service/dto/response/HappinessSubRoutineListGetServiceResponse.java deleted file mode 100644 index a2b55d8b..00000000 --- a/src/main/java/com/soptie/server/routine/service/dto/response/HappinessSubRoutineListGetServiceResponse.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.soptie.server.routine.service.dto.response; - -import static lombok.AccessLevel.PRIVATE; - -import java.util.List; - -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.service.vo.ChallengeVO; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record HappinessSubRoutineListGetServiceResponse( - String routineContent, String themeName, String themeColor, - String iconImageUrl, String backgroundImageUrl, - List challenges -) { - - public static HappinessSubRoutineListGetServiceResponse of(Routine routine, List challenges) { - return HappinessSubRoutineListGetServiceResponse.builder() - .routineContent(routine.getContent()) - .themeName(routine.getTheme().getName()) - .themeColor(routine.getTheme().getColor()) - .iconImageUrl(routine.getTheme().getImageLinks().getIconImageUrl()) - .backgroundImageUrl(routine.getTheme().getImageLinks().getHappinessCardImageUrl()) - .challenges(challenges.stream().map(HappinessSubRoutineServiceResponse::of).toList()) - .build(); - } - - @Builder(access = PRIVATE) - public record HappinessSubRoutineServiceResponse( - long challengeId, String content, String description, - String requiredTime, String place - ) { - - private static HappinessSubRoutineServiceResponse of(ChallengeVO challenge) { - return HappinessSubRoutineServiceResponse.builder() - .challengeId(challenge.challengeId()) - .content(challenge.content()) - .description(challenge.description()) - .requiredTime(challenge.requiredTime()) - .place(challenge.place()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/routine/service/vo/ChallengeVO.java b/src/main/java/com/soptie/server/routine/service/vo/ChallengeVO.java deleted file mode 100644 index 8553b2ed..00000000 --- a/src/main/java/com/soptie/server/routine/service/vo/ChallengeVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.soptie.server.routine.service.vo; - -import com.soptie.server.routine.entity.Challenge; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = AccessLevel.PRIVATE) -public record ChallengeVO( - long challengeId, - @NonNull String content, - @NonNull String description, - @NonNull String requiredTime, - @NonNull String place -) { - - public static ChallengeVO from(Challenge challenge) { - return ChallengeVO.builder() - .challengeId(challenge.getId()) - .content(challenge.getContent()) - .description(challenge.getDescription()) - .requiredTime(challenge.getRequiredTime()) - .place(challenge.getPlace()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/routine/service/vo/RoutineVO.java b/src/main/java/com/soptie/server/routine/service/vo/RoutineVO.java deleted file mode 100644 index d91ecf84..00000000 --- a/src/main/java/com/soptie/server/routine/service/vo/RoutineVO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.soptie.server.routine.service.vo; - -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.service.vo.ThemeVO; - -import jakarta.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.Builder; - -@Builder(access = AccessLevel.PRIVATE) -public record RoutineVO( - long routineId, - @NotNull String content, - @NotNull RoutineType routineType, - ThemeVO theme -) { - - public static RoutineVO from(Routine routine) { - return RoutineVO.builder() - .routineId(routine.getId()) - .content(routine.getContent()) - .routineType(routine.getType()) - .build(); - } - - public static RoutineVO from(Routine routine, Theme theme) { - return RoutineVO.builder() - .routineId(routine.getId()) - .content(routine.getContent()) - .routineType(routine.getType()) - .theme(ThemeVO.from(theme)) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/theme/adapter/ThemeFinder.java b/src/main/java/com/soptie/server/theme/adapter/ThemeFinder.java deleted file mode 100644 index 1402371c..00000000 --- a/src/main/java/com/soptie/server/theme/adapter/ThemeFinder.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.soptie.server.theme.adapter; - -import static com.soptie.server.theme.message.ThemeErrorCode.INVALID_THEME; - -import java.util.List; - -import com.soptie.server.common.support.RepositoryAdapter; -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.exception.ThemeException; -import com.soptie.server.theme.repository.ThemeRepository; - -import lombok.RequiredArgsConstructor; - -@RepositoryAdapter -@RequiredArgsConstructor -public class ThemeFinder { - - private final ThemeRepository themeRepository; - - public List findAllOrderByNameAsc() { - return themeRepository.findAllOrderByNameAsc(); - } - - public Theme findById(long id) { - return themeRepository.findById(id) - .orElseThrow(() -> new ThemeException(INVALID_THEME)); - } - - public List findAllInBasic() { - return themeRepository.findAllInBasic(); - } - - public boolean isExistById(long id) { - return themeRepository.existsById(id); - } -} diff --git a/src/main/java/com/soptie/server/theme/controller/v1/DailyThemeController.java b/src/main/java/com/soptie/server/theme/controller/v1/DailyThemeController.java deleted file mode 100644 index 311c3634..00000000 --- a/src/main/java/com/soptie/server/theme/controller/v1/DailyThemeController.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.soptie.server.theme.controller.v1; - -import static com.soptie.server.common.dto.SuccessResponse.*; -import static com.soptie.server.theme.message.ThemeSuccessMessage.*; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.theme.controller.v1.docs.DailyThemeControllerDocs; -import com.soptie.server.theme.controller.v1.dto.response.DailyThemeListGetResponse; -import com.soptie.server.theme.service.ThemeService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/routines/daily/themes") -public class DailyThemeController implements DailyThemeControllerDocs { - - private final ThemeService themeService; - - @GetMapping - public ResponseEntity> acquireAllInBasic() { - val response = DailyThemeListGetResponse.from(themeService.acquireAllInBasic()); - return ResponseEntity.ok(success(SUCCESS_GET_THEME.getMessage(), response)); - } -} diff --git a/src/main/java/com/soptie/server/theme/controller/v1/HappinessThemeController.java b/src/main/java/com/soptie/server/theme/controller/v1/HappinessThemeController.java deleted file mode 100644 index 5656504c..00000000 --- a/src/main/java/com/soptie/server/theme/controller/v1/HappinessThemeController.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.soptie.server.theme.controller.v1; - -import static com.soptie.server.common.dto.SuccessResponse.*; -import static com.soptie.server.theme.message.ThemeSuccessMessage.*; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.theme.controller.v1.docs.HappinessThemeControllerDocs; -import com.soptie.server.theme.controller.v1.dto.response.HappinessThemeListGetResponse; -import com.soptie.server.theme.service.ThemeService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/routines/happiness/themes") -public class HappinessThemeController implements HappinessThemeControllerDocs { - - private final ThemeService themeService; - - @GetMapping - public ResponseEntity> acquireAllInBasic() { - val response = HappinessThemeListGetResponse.from(themeService.acquireAllInBasic()); - return ResponseEntity.ok(success(SUCCESS_GET_HAPPINESS_THEME.getMessage(), response)); - } -} diff --git a/src/main/java/com/soptie/server/theme/controller/v1/docs/DailyThemeControllerDocs.java b/src/main/java/com/soptie/server/theme/controller/v1/docs/DailyThemeControllerDocs.java deleted file mode 100644 index e527e48e..00000000 --- a/src/main/java/com/soptie/server/theme/controller/v1/docs/DailyThemeControllerDocs.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.soptie.server.theme.controller.v1.docs; - -import org.springframework.http.ResponseEntity; - -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.theme.controller.v1.dto.response.DailyThemeListGetResponse; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "daily themes V1", description = "데일리 테마 API Version1") -public interface DailyThemeControllerDocs { - - @Operation( - summary = "데일리 루틴 테마 목록 조회", - description = "데일리 루틴 테마 전체를 조회한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "4xx", - description = "클라이언트(요청) 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))} - ) - ResponseEntity> acquireAllInBasic(); -} diff --git a/src/main/java/com/soptie/server/theme/controller/v1/docs/HappinessThemeControllerDocs.java b/src/main/java/com/soptie/server/theme/controller/v1/docs/HappinessThemeControllerDocs.java deleted file mode 100644 index 5118536e..00000000 --- a/src/main/java/com/soptie/server/theme/controller/v1/docs/HappinessThemeControllerDocs.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.soptie.server.theme.controller.v1.docs; - -import org.springframework.http.ResponseEntity; - -import com.soptie.server.common.dto.ErrorResponse; -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.theme.controller.v1.dto.response.HappinessThemeListGetResponse; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "happiness theme V1", description = "행복 테마 API Version1") -public interface HappinessThemeControllerDocs { - - @Operation( - summary = "행복 루틴 테마 목록 조회", - description = "행복 루틴 테마 전체를 조회한다.", - responses = { - @ApiResponse(responseCode = "200", description = "성공"), - @ApiResponse( - responseCode = "500", - description = "서버 내부 오류", - content = @Content(schema = @Schema(implementation = ErrorResponse.class)))}) - ResponseEntity> acquireAllInBasic(); - -} diff --git a/src/main/java/com/soptie/server/theme/controller/v1/dto/response/DailyThemeListGetResponse.java b/src/main/java/com/soptie/server/theme/controller/v1/dto/response/DailyThemeListGetResponse.java deleted file mode 100644 index fd936410..00000000 --- a/src/main/java/com/soptie/server/theme/controller/v1/dto/response/DailyThemeListGetResponse.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.soptie.server.theme.controller.v1.dto.response; - -import static lombok.AccessLevel.PRIVATE; - -import java.util.List; - -import com.soptie.server.theme.service.vo.ThemeVO; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record DailyThemeListGetResponse( - @NonNull List themes -) { - - public static DailyThemeListGetResponse from(List themes) { - return DailyThemeListGetResponse.builder() - .themes(themes.stream().map(DailyThemeResponse::from).toList()) - .build(); - } - - @Builder(access = PRIVATE) - private record DailyThemeResponse( - long themeId, - @NonNull String name, - @NonNull String iconImageUrl, - @NonNull String backgroundImageUrl - ) { - - private static DailyThemeResponse from(ThemeVO theme) { - return DailyThemeResponse.builder() - .themeId(theme.themeId()) - .name(theme.name()) - .iconImageUrl(theme.imageLinks().dailyIconImageUrl()) - .backgroundImageUrl(theme.imageLinks().dailyCardImageUrl()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/theme/controller/v1/dto/response/HappinessThemeListGetResponse.java b/src/main/java/com/soptie/server/theme/controller/v1/dto/response/HappinessThemeListGetResponse.java deleted file mode 100644 index 92669c93..00000000 --- a/src/main/java/com/soptie/server/theme/controller/v1/dto/response/HappinessThemeListGetResponse.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.soptie.server.theme.controller.v1.dto.response; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import com.soptie.server.theme.service.vo.ThemeVO; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record HappinessThemeListGetResponse(@NonNull List themes) { - - public static HappinessThemeListGetResponse from(List themes) { - return HappinessThemeListGetResponse.builder() - .themes(themes.stream().map(HappinessThemeResponse::from).toList()) - .build(); - } - - @Builder - public record HappinessThemeResponse(long themeId, @NonNull String name) { - - private static HappinessThemeResponse from(ThemeVO theme) { - return HappinessThemeResponse.builder().themeId(theme.themeId()).name(theme.name()).build(); - } - } -} diff --git a/src/main/java/com/soptie/server/theme/controller/v2/ThemeControllerV2.java b/src/main/java/com/soptie/server/theme/controller/v2/ThemeControllerV2.java deleted file mode 100644 index 7d5ffb62..00000000 --- a/src/main/java/com/soptie/server/theme/controller/v2/ThemeControllerV2.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.soptie.server.theme.controller.v2; - -import static com.soptie.server.common.dto.SuccessResponse.success; -import static com.soptie.server.theme.message.ThemeSuccessMessage.SUCCESS_ACQUIRE_ALL; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.theme.controller.v2.docs.ThemeControllerV2Docs; -import com.soptie.server.theme.controller.v2.dto.response.ThemeListAcquireResponse; -import com.soptie.server.theme.service.ThemeService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v2/themes") -public class ThemeControllerV2 implements ThemeControllerV2Docs { - - private final ThemeService themeService; - - @GetMapping - public ResponseEntity> acquireAllInBasic() { - val response = ThemeListAcquireResponse.from(themeService.acquireAllInBasic()); - return ResponseEntity.ok(success(SUCCESS_ACQUIRE_ALL.getMessage(), response)); - } -} diff --git a/src/main/java/com/soptie/server/theme/controller/v2/dto/response/ThemeListAcquireResponse.java b/src/main/java/com/soptie/server/theme/controller/v2/dto/response/ThemeListAcquireResponse.java deleted file mode 100644 index a1bfb8d5..00000000 --- a/src/main/java/com/soptie/server/theme/controller/v2/dto/response/ThemeListAcquireResponse.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.soptie.server.theme.controller.v2.dto.response; - -import static lombok.AccessLevel.*; - -import java.util.List; - -import com.soptie.server.theme.service.vo.ThemeVO; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record ThemeListAcquireResponse( - @NonNull List themes -) { - - public static ThemeListAcquireResponse from(List themes) { - return ThemeListAcquireResponse.builder() - .themes(themes.stream().map(ThemeResponse::from).toList()) - .build(); - } - - @Builder(access = PRIVATE) - private record ThemeResponse( - long themeId, - @NonNull String title, - @NonNull String subTitle, - @NonNull String description - ) { - - private static ThemeResponse from(ThemeVO theme) { - return ThemeResponse.builder() - .themeId(theme.themeId()) - .title(theme.name()) - .subTitle(theme.modifier()) - .description(theme.description()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/theme/entity/Theme.java b/src/main/java/com/soptie/server/theme/entity/Theme.java deleted file mode 100644 index 89291791..00000000 --- a/src/main/java/com/soptie/server/theme/entity/Theme.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.soptie.server.theme.entity; - -import static jakarta.persistence.EnumType.*; -import static jakarta.persistence.GenerationType.*; - -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -@Getter -public class Theme { - - @Id - @GeneratedValue(strategy = IDENTITY) - @Column(name = "theme_id") - private Long id; - - @Column(nullable = false) - private String name; - - @Column(nullable = false) - private String modifier; - - @Embedded - private ThemeImageLinks imageLinks; - - private String color; - - @Column(columnDefinition = "TEXT", nullable = false) - private String description; - - @Enumerated(value = STRING) - @Column(nullable = false) - private ThemeType type; - - public Theme( - Long id, - String name, - String modifier, - String description, - String color, - ThemeType type, - ThemeImageLinks imageLinks - ) { - this.id = id; - this.name = name; - this.modifier = modifier; - this.description = description; - this.color = color; - this.type = type; - this.imageLinks = imageLinks; - } -} diff --git a/src/main/java/com/soptie/server/theme/entity/ThemeImageLinks.java b/src/main/java/com/soptie/server/theme/entity/ThemeImageLinks.java deleted file mode 100644 index 17bf04f6..00000000 --- a/src/main/java/com/soptie/server/theme/entity/ThemeImageLinks.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.soptie.server.theme.entity; - -import jakarta.persistence.Embeddable; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Embeddable -@NoArgsConstructor -@Getter -public class ThemeImageLinks { - - private String iconImageUrl; - - private String backgroundImageUrl; - - private String dailyCardImageUrl; - - private String dailyIconImageUrl; - - private String happinessCardImageUrl; - - public ThemeImageLinks(String iconImageUrl, String backgroundImageUrl, String dailyCardImageUrl, - String dailyIconImageUrl, String happinessCardImageUrl) { - this.iconImageUrl = iconImageUrl; - this.backgroundImageUrl = backgroundImageUrl; - this.dailyCardImageUrl = dailyCardImageUrl; - this.dailyIconImageUrl = dailyIconImageUrl; - this.happinessCardImageUrl = happinessCardImageUrl; - } -} diff --git a/src/main/java/com/soptie/server/theme/entity/ThemeType.java b/src/main/java/com/soptie/server/theme/entity/ThemeType.java deleted file mode 100644 index edc314f1..00000000 --- a/src/main/java/com/soptie/server/theme/entity/ThemeType.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.soptie.server.theme.entity; - -public enum ThemeType { - BASIC, - MAKER -} diff --git a/src/main/java/com/soptie/server/theme/exception/ThemeException.java b/src/main/java/com/soptie/server/theme/exception/ThemeException.java deleted file mode 100644 index 68a34cbd..00000000 --- a/src/main/java/com/soptie/server/theme/exception/ThemeException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.soptie.server.theme.exception; - -import com.soptie.server.theme.message.ThemeErrorCode; - -import lombok.Getter; - -@Getter -public class ThemeException extends RuntimeException { - - private final ThemeErrorCode errorCode; - - public ThemeException(ThemeErrorCode errorCode) { - super("[ThemeException] : " + errorCode.getMessage()); - this.errorCode = errorCode; - } -} diff --git a/src/main/java/com/soptie/server/theme/message/ThemeErrorCode.java b/src/main/java/com/soptie/server/theme/message/ThemeErrorCode.java deleted file mode 100644 index b9629583..00000000 --- a/src/main/java/com/soptie/server/theme/message/ThemeErrorCode.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.soptie.server.theme.message; - -import static org.springframework.http.HttpStatus.*; - -import org.springframework.http.HttpStatus; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public enum ThemeErrorCode { - - /* 404 NOT_FOUND : 자원을 찾을 수 없음 */ - INVALID_THEME(NOT_FOUND, "유효하지 않은 테마입니다."); - - private final HttpStatus httpStatus; - private final String message; -} diff --git a/src/main/java/com/soptie/server/theme/message/ThemeSuccessMessage.java b/src/main/java/com/soptie/server/theme/message/ThemeSuccessMessage.java deleted file mode 100644 index 80d5da74..00000000 --- a/src/main/java/com/soptie/server/theme/message/ThemeSuccessMessage.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.soptie.server.theme.message; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum ThemeSuccessMessage { - - SUCCESS_GET_THEME("데일리 루틴 테마 조회 성공"), - SUCCESS_GET_HAPPINESS_THEME("행복 루틴 테마 조회 성공"), - SUCCESS_ACQUIRE_ALL("테마 목록 조회 성공"); - - private final String message; -} diff --git a/src/main/java/com/soptie/server/theme/repository/ThemeCustomRepository.java b/src/main/java/com/soptie/server/theme/repository/ThemeCustomRepository.java deleted file mode 100644 index 09f77b84..00000000 --- a/src/main/java/com/soptie/server/theme/repository/ThemeCustomRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.soptie.server.theme.repository; - -import java.util.List; - -import com.soptie.server.theme.entity.Theme; - -public interface ThemeCustomRepository { - List findAllOrderByNameAsc(); - - List findAllInBasic(); -} diff --git a/src/main/java/com/soptie/server/theme/repository/ThemeRepository.java b/src/main/java/com/soptie/server/theme/repository/ThemeRepository.java deleted file mode 100644 index 66a8e9dc..00000000 --- a/src/main/java/com/soptie/server/theme/repository/ThemeRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.soptie.server.theme.repository; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.soptie.server.theme.entity.Theme; - -public interface ThemeRepository extends JpaRepository, ThemeCustomRepository { -} diff --git a/src/main/java/com/soptie/server/theme/repository/ThemeRepositoryImpl.java b/src/main/java/com/soptie/server/theme/repository/ThemeRepositoryImpl.java deleted file mode 100644 index 9b2a446b..00000000 --- a/src/main/java/com/soptie/server/theme/repository/ThemeRepositoryImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.soptie.server.theme.repository; - -import static com.soptie.server.theme.entity.QTheme.*; - -import java.util.List; - -import org.springframework.stereotype.Repository; - -import com.querydsl.jpa.impl.JPAQueryFactory; -import com.soptie.server.common.support.ExpressionGenerator; -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.entity.ThemeType; - -import lombok.RequiredArgsConstructor; - -@Repository -@RequiredArgsConstructor -public class ThemeRepositoryImpl implements ThemeCustomRepository { - - private final JPAQueryFactory queryFactory; - - @Override - public List findAllOrderByNameAsc() { - return queryFactory - .selectFrom(theme) - .orderBy(ExpressionGenerator.getFirstLetter(theme.name).asc()) - .fetch(); - } - - @Override - public List findAllInBasic() { - //TODO: 무지개 순 정렬 추가 - return queryFactory - .selectFrom(theme) - .where(theme.type.eq(ThemeType.BASIC)) - .fetch(); - } -} diff --git a/src/main/java/com/soptie/server/theme/service/ThemeService.java b/src/main/java/com/soptie/server/theme/service/ThemeService.java deleted file mode 100644 index 67411865..00000000 --- a/src/main/java/com/soptie/server/theme/service/ThemeService.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.soptie.server.theme.service; - -import java.util.List; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.theme.adapter.ThemeFinder; -import com.soptie.server.theme.service.vo.ThemeVO; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class ThemeService { - - private final ThemeFinder themeFinder; - - public List acquireAllInBasic() { - val themes = themeFinder.findAllInBasic(); - return themes.stream().map(ThemeVO::from).toList(); - } - - public ThemeVO acquireById(long themeId) { - return ThemeVO.from(themeFinder.findById(themeId)); - } -} diff --git a/src/main/java/com/soptie/server/theme/service/vo/ThemeImageLinksVO.java b/src/main/java/com/soptie/server/theme/service/vo/ThemeImageLinksVO.java deleted file mode 100644 index d0ea9505..00000000 --- a/src/main/java/com/soptie/server/theme/service/vo/ThemeImageLinksVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.soptie.server.theme.service.vo; - -import static lombok.AccessLevel.*; - -import com.soptie.server.theme.entity.ThemeImageLinks; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record ThemeImageLinksVO( - String iconImageUrl, - String backgroundImageUrl, - String dailyCardImageUrl, - String dailyIconImageUrl, - String happinessCardImageUrl -) { - - public static ThemeImageLinksVO from(ThemeImageLinks imageLinks) { - return ThemeImageLinksVO.builder() - .iconImageUrl(imageLinks.getIconImageUrl()) - .backgroundImageUrl(imageLinks.getBackgroundImageUrl()) - .dailyCardImageUrl(imageLinks.getDailyCardImageUrl()) - .dailyIconImageUrl(imageLinks.getDailyIconImageUrl()) - .happinessCardImageUrl(imageLinks.getHappinessCardImageUrl()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/theme/service/vo/ThemeVO.java b/src/main/java/com/soptie/server/theme/service/vo/ThemeVO.java deleted file mode 100644 index dd76da29..00000000 --- a/src/main/java/com/soptie/server/theme/service/vo/ThemeVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.soptie.server.theme.service.vo; - -import static lombok.AccessLevel.*; - -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.entity.ThemeType; - -import lombok.Builder; -import lombok.NonNull; - -@Builder(access = PRIVATE) -public record ThemeVO( - long themeId, - @NonNull String name, - @NonNull String modifier, - @NonNull String description, - @NonNull ThemeType themeType, - @NonNull ThemeImageLinksVO imageLinks, - @NonNull String color -) { - - public static ThemeVO from(Theme theme) { - return ThemeVO.builder() - .themeId(theme.getId()) - .name(theme.getName()) - .modifier(theme.getModifier()) - .description(theme.getDescription()) - .themeType(theme.getType()) - .imageLinks(ThemeImageLinksVO.from(theme.getImageLinks())) - .color(theme.getColor()) - .build(); - } -} diff --git a/src/main/java/com/soptie/server/version/controller/VersionController.java b/src/main/java/com/soptie/server/version/controller/VersionController.java deleted file mode 100644 index 680ec808..00000000 --- a/src/main/java/com/soptie/server/version/controller/VersionController.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.soptie.server.version.controller; - -import static com.soptie.server.version.message.SuccessMessage.*; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.soptie.server.common.dto.SuccessResponse; -import com.soptie.server.version.controller.docs.VersionControllerDocs; -import com.soptie.server.version.controller.dto.response.AppVersionGetResponse; -import com.soptie.server.version.service.VersionService; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/versions") -public class VersionController implements VersionControllerDocs { - - private final VersionService versionService; - - @GetMapping("/client/app") - public ResponseEntity> getClientAppVersion() { - val response = AppVersionGetResponse.of(versionService.getClientAppVersion()); - return ResponseEntity.ok(SuccessResponse.success(SUCCESS_GET_APP_VERSION.getMessage(), response)); - } -} diff --git a/src/main/java/com/soptie/server/version/controller/dto/response/AppVersionGetResponse.java b/src/main/java/com/soptie/server/version/controller/dto/response/AppVersionGetResponse.java deleted file mode 100644 index 4472264c..00000000 --- a/src/main/java/com/soptie/server/version/controller/dto/response/AppVersionGetResponse.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.soptie.server.version.controller.dto.response; - -import static lombok.AccessLevel.PRIVATE; - -import com.soptie.server.version.service.dto.response.AppVersionGetServiceResponse; -import com.soptie.server.version.service.dto.response.AppVersionGetServiceResponse.VersionServiceResponse; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record AppVersionGetResponse( - VersionResponse iosVersion, - VersionResponse androidVersion, - String notificationTitle, - String notificationContent -) { - - public static AppVersionGetResponse of(AppVersionGetServiceResponse response) { - return AppVersionGetResponse.builder() - .iosVersion(VersionResponse.of(response.iosVersion())) - .androidVersion(VersionResponse.of(response.androidVersion())) - .notificationTitle(response.notificationTitle()) - .notificationContent(response.notificationContent()) - .build(); - } - - @Builder(access = PRIVATE) - private record VersionResponse( - String appVersion, - String forceUpdateVersion - ) { - - private static VersionResponse of(VersionServiceResponse response) { - return VersionResponse.builder() - .appVersion(response.appVersion()) - .forceUpdateVersion(response.forceUpdateVersion()) - .build(); - } - } -} diff --git a/src/main/java/com/soptie/server/version/message/SuccessMessage.java b/src/main/java/com/soptie/server/version/message/SuccessMessage.java deleted file mode 100644 index 5d240b14..00000000 --- a/src/main/java/com/soptie/server/version/message/SuccessMessage.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.soptie.server.version.message; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum SuccessMessage { - - SUCCESS_GET_APP_VERSION("버전 정보 조회 성공"); - - private final String message; -} diff --git a/src/main/java/com/soptie/server/version/service/VersionService.java b/src/main/java/com/soptie/server/version/service/VersionService.java deleted file mode 100644 index e7753013..00000000 --- a/src/main/java/com/soptie/server/version/service/VersionService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.soptie.server.version.service; - -import com.soptie.server.version.service.dto.response.AppVersionGetServiceResponse; - -public interface VersionService { - AppVersionGetServiceResponse getClientAppVersion(); -} diff --git a/src/main/java/com/soptie/server/version/service/dto/response/AppVersionGetServiceResponse.java b/src/main/java/com/soptie/server/version/service/dto/response/AppVersionGetServiceResponse.java deleted file mode 100644 index 20ede984..00000000 --- a/src/main/java/com/soptie/server/version/service/dto/response/AppVersionGetServiceResponse.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.soptie.server.version.service.dto.response; - -import static lombok.AccessLevel.*; - -import lombok.Builder; - -@Builder(access = PRIVATE) -public record AppVersionGetServiceResponse( - VersionServiceResponse iosVersion, - VersionServiceResponse androidVersion, - String notificationTitle, - String notificationContent -) { - - public static AppVersionGetServiceResponse of( - String iosAppVersion, - String iosForceUpdateVersion, - String androidAppVersion, - String androidForceUpdateVersion, - String notificationTitle, - String notificationContent - ) { - return AppVersionGetServiceResponse.builder() - .iosVersion(VersionServiceResponse.of(iosAppVersion, iosForceUpdateVersion)) - .androidVersion(VersionServiceResponse.of(androidAppVersion, androidForceUpdateVersion)) - .notificationTitle(notificationTitle) - .notificationContent(notificationContent) - .build(); - } - - @Builder(access = PRIVATE) - public record VersionServiceResponse( - String appVersion, - String forceUpdateVersion - ) { - - private static VersionServiceResponse of(String appVersion, String forceUpdateVersion) { - return VersionServiceResponse.builder() - .appVersion(appVersion) - .forceUpdateVersion(forceUpdateVersion) - .build(); - } - } -} diff --git a/src/test/java/com/soptie/server/auth/service/AuthServiceImplTest.java b/src/test/java/com/soptie/server/auth/service/AuthServiceImplTest.java deleted file mode 100644 index 251f5101..00000000 --- a/src/test/java/com/soptie/server/auth/service/AuthServiceImplTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.soptie.server.auth.service; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.Optional; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.soptie.server.auth.jwt.JwtTokenProvider; -import com.soptie.server.auth.jwt.UserAuthentication; -import com.soptie.server.auth.service.dto.request.TokenGetServiceRequest; -import com.soptie.server.auth.service.dto.response.TokenGetServiceResponse; -import com.soptie.server.common.config.ValueConfig; -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.repository.MemberRepository; -import com.soptie.server.support.fixture.MemberFixture; - -@ExtendWith(MockitoExtension.class) -class AuthServiceImplTest { - - @InjectMocks - private AuthServiceImpl authService; - - @Mock - private MemberRepository memberRepository; - - @Mock - private ValueConfig valueConfig; - - @Mock - private JwtTokenProvider jwtTokenProvider; - - @Test - @DisplayName("로그아웃을 하면 리프레시 토큰 값이 null이 된다.") - void emptyRefreshTokenAfterLogout() { - // given - long memberId = 1L; - Member member = member(memberId); - doReturn(Optional.of(member)).when(memberRepository).findById(memberId); - member.updateRefreshToken("refreshToken"); - - // when - authService.signOut(member.getId()); - - // then - assertThat(member.getRefreshToken()).isNull(); - } - - @Test - @DisplayName("파러미터로 받은 리프레시 토큰을 가지고 있는 멤버가 있다면 액세스 토큰을 재발급 해준다.") - void refreshAccessTokenForMemberWithRefreshToken() { - // given - long memberId = 1L; - Member member = member(memberId); - String token = "refreshToken"; - doReturn(Optional.of(member)).when(memberRepository).findByRefreshToken(token); - // doReturn("Bearer ").when(valueConfig).getBEARER_HEADER(); - // doReturn("").when(valueConfig).getBLANK(); - doReturn(60000L).when(valueConfig).getAccessTokenExpired(); - doReturn(token).when(jwtTokenProvider) - .generateToken(new UserAuthentication(member.getId(), null, null), 60000L); - - // when - TokenGetServiceResponse result = authService.reissueToken(TokenGetServiceRequest.of("Bearer " + token)); - - // then - assertThat(result).isEqualTo(TokenGetServiceResponse.of(token)); - } - - private Member member(long memberId) { - Member member = MemberFixture.member().id(memberId).build(); - return member; - } -} diff --git a/src/test/java/com/soptie/server/doll/service/DollServiceImplTest.java b/src/test/java/com/soptie/server/doll/service/DollServiceImplTest.java deleted file mode 100644 index 8c2ae574..00000000 --- a/src/test/java/com/soptie/server/doll/service/DollServiceImplTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.soptie.server.doll.service; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.Optional; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.soptie.server.doll.dto.DollImageResponse; -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.doll.repository.DollRepository; -import com.soptie.server.support.fixture.DollFixture; - -@ExtendWith(MockitoExtension.class) -class DollServiceImplTest { - - @InjectMocks - private DollServiceImpl dollService; - - @Mock - private DollRepository dollRepository; - - @ParameterizedTest - @DisplayName("인형 타입에 해당하는 인형 이미지 주소를 토대로 DollImageResponse를 생성한다.") - @CsvSource(value = {"brown, BROWN", "gray, GRAY", "red, RED", "white, WHITE"}) - void acquireImageUriByDollType(String faceImageUrl, DollType dollType) { - // given - Long id = 1L; - Doll doll = doll(id, dollType, faceImageUrl); - - // when - DollImageResponse response = dollService.getDollImage(dollType); - - // then - assertThat(DollImageResponse.of(doll)).isEqualTo(response); - } - - private Doll doll(Long id, DollType dollType, String faceImageUrl) { - Doll doll = DollFixture.doll().id(id).dollType(dollType).faceImageUrl(faceImageUrl).build(); - doReturn(Optional.of(doll)).when(dollRepository).findByDollType(dollType); - return doll; - } -} diff --git a/src/test/java/com/soptie/server/domain/auth/AuthServiceImplTest.java b/src/test/java/com/soptie/server/domain/auth/AuthServiceImplTest.java new file mode 100644 index 00000000..12918aee --- /dev/null +++ b/src/test/java/com/soptie/server/domain/auth/AuthServiceImplTest.java @@ -0,0 +1,34 @@ +package com.soptie.server.domain.auth; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class AuthServiceImplTest { + + @InjectMocks + private AuthService authService; + + @Test + @DisplayName("로그아웃을 하면 리프레시 토큰 값이 null이 된다.") + void resetRefreshTokenIfSignOut() { //TODO: 테스트 + // given + + // when + + // then + } + + @Test + @DisplayName("파러미터로 받은 리프레시 토큰을 가지고 있는 멤버가 있다면 액세스 토큰을 재발급 해준다.") + void reissueTokenIfMemberHasSameRefreshToken() { //TODO: 테스트 + // given + + // when + + // then + } +} diff --git a/src/test/java/com/soptie/server/domain/doll/DollServiceTest.java b/src/test/java/com/soptie/server/domain/doll/DollServiceTest.java new file mode 100644 index 00000000..39c9777a --- /dev/null +++ b/src/test/java/com/soptie/server/domain/doll/DollServiceTest.java @@ -0,0 +1,33 @@ +package com.soptie.server.domain.doll; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.soptie.server.domain.member.MemberService; +import com.soptie.server.persistence.repository.DollRepository; + +@ExtendWith(MockitoExtension.class) +class DollServiceTest { + + @InjectMocks + private MemberService memberService; + + @Mock + private DollRepository dollRepository; + + @ParameterizedTest + @DisplayName("[성공] 인형 타입에 해당하는 인형 이미지 주소를 토대로 DollImageResponse를 생성한다.") + @CsvSource(value = {"brown, BROWN", "gray, GRAY", "red, RED", "white, WHITE"}) + void acquireImageUriByDollType(String faceImageUrl, DollType dollType) { // TODO: 테스트 + // given + + // when + + // then + } +} diff --git a/src/test/java/com/soptie/server/domain/maker/MakerServiceTest.java b/src/test/java/com/soptie/server/domain/maker/MakerServiceTest.java new file mode 100644 index 00000000..63cbc00a --- /dev/null +++ b/src/test/java/com/soptie/server/domain/maker/MakerServiceTest.java @@ -0,0 +1,25 @@ +package com.soptie.server.domain.maker; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class MakerServiceTest { + + @InjectMocks + private MakerService makerService; + + @Test + @DisplayName("[성공] 메이커와 해당하는 테마 정보를 조회한다.") + void getMakersWithTheme() { //TODO: 테스트 + // given + + // when + + // then + } + +} diff --git a/src/test/java/com/soptie/server/domain/member/MemberServiceTest.java b/src/test/java/com/soptie/server/domain/member/MemberServiceTest.java new file mode 100644 index 00000000..244efdff --- /dev/null +++ b/src/test/java/com/soptie/server/domain/member/MemberServiceTest.java @@ -0,0 +1,54 @@ +package com.soptie.server.domain.member; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class MemberServiceTest { + + @InjectMocks + private MemberService memberService; + + @Test + @DisplayName("[성공] 응답이 유효하면 회원 프로필이 생성된다.") + void createMemberProfileSuccessfully() { //TODO: 테스트 + // given + + // when + + // then + } + + @Test + @DisplayName("솜뭉치 개수가 양수일 때 솜뭉치를 줄 수 있다.") + void canGiveCottonWhenCottonCountIsPositive() { //TODO: 테스트 + // given + + // when + + // then + } + + @Test + @DisplayName("솜뭉치 개수가 0일 때 솜뭉치를 주려 하면 예외가 발생한다.") + void occurExceptionGiveCottonWhenCottonCountIsZero() { //TODO: 테스트 + // given + + // when + + // then + } + + @Test + @DisplayName("멤버의 멤버 인형 정보와 솜뭉치 개수를 가져온다.") + void getMemberProfile() { //TODO: 테스트 + // given + + // when + + // then + } +} diff --git a/src/test/java/com/soptie/server/domain/memberdoll/MemberDollServiceTest.java b/src/test/java/com/soptie/server/domain/memberdoll/MemberDollServiceTest.java new file mode 100644 index 00000000..288f63c6 --- /dev/null +++ b/src/test/java/com/soptie/server/domain/memberdoll/MemberDollServiceTest.java @@ -0,0 +1,35 @@ +package com.soptie.server.domain.memberdoll; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.soptie.server.domain.member.MemberService; +import com.soptie.server.persistence.repository.DollRepository; +import com.soptie.server.persistence.repository.MemberDollRepository; + +@ExtendWith(MockitoExtension.class) +class MemberDollServiceTest { + + @InjectMocks + private MemberService memberService; + + @Mock + private DollRepository dollRepository; + + @Mock + private MemberDollRepository memberDollRepository; + + @Test + @DisplayName("멤버 인형을 생성하고 이를 멤버의 멤버 인형으로 설정한다.") + void createMemberDollAndSetMember() { //TODO: 테스트 + // given + + // when + + // then + } +} diff --git a/src/test/java/com/soptie/server/domain/memberroutine/MemberRoutineServiceTest.java b/src/test/java/com/soptie/server/domain/memberroutine/MemberRoutineServiceTest.java new file mode 100644 index 00000000..2fcf5ae1 --- /dev/null +++ b/src/test/java/com/soptie/server/domain/memberroutine/MemberRoutineServiceTest.java @@ -0,0 +1,26 @@ +package com.soptie.server.domain.memberroutine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@ExtendWith(MockitoExtension.class) +class MemberRoutineServiceTest { + @InjectMocks + private MemberRoutineService memberRoutineService; + + @Test + @DisplayName("[성공] 회원이 추가한 루틴을 조회횐다.") + void getMemberRoutines() { //TODO: 테스트 + // given + + // when + + // then + } +} diff --git a/src/test/java/com/soptie/server/domain/routine/RoutineServiceTest.java b/src/test/java/com/soptie/server/domain/routine/RoutineServiceTest.java new file mode 100644 index 00000000..1fa7c8d8 --- /dev/null +++ b/src/test/java/com/soptie/server/domain/routine/RoutineServiceTest.java @@ -0,0 +1,23 @@ +package com.soptie.server.domain.routine; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class RoutineServiceTest { + @InjectMocks + RoutineService routineService; + + @Test + @DisplayName("[성공] 회원의 진행 유무를 포함한 루틴을 테마별로 조회한다.") + void getRoutinesByThemeId() { //TODO: test + // given + + // when + + // then + } +} diff --git a/src/test/java/com/soptie/server/maker/service/integration/MakerServiceIntegrationTest.java b/src/test/java/com/soptie/server/maker/service/integration/MakerServiceIntegrationTest.java deleted file mode 100644 index f10a4a35..00000000 --- a/src/test/java/com/soptie/server/maker/service/integration/MakerServiceIntegrationTest.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.soptie.server.maker.service.integration; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.maker.entity.Maker; -import com.soptie.server.maker.repository.MakerRepository; -import com.soptie.server.maker.service.MakerService; -import com.soptie.server.maker.service.dto.MakerListAcquireServiceResponse; -import com.soptie.server.support.IntegrationTest; -import com.soptie.server.support.fixture.MakerFixture; -import com.soptie.server.support.fixture.ThemeFixture; -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.repository.ThemeRepository; - -@IntegrationTest -@Transactional -public class MakerServiceIntegrationTest { - - @Autowired - MakerService makerService; - - @Autowired - MakerRepository makerRepository; - - @Autowired - ThemeRepository themeRepository; - - @Nested - class Acquire { - - Maker maker1; - Maker maker2; - Theme theme1; - Theme theme2; - long makerId1 = 1L; - long makerId2 = 2L; - long themeId1 = 1L; - long themeId2 = 2L; - String name = "maker"; - String job = "job"; - String profileImageUrl = "profileImageUrl"; - String content = "content"; - List tags = List.of("#tag1", "#tag2", "#tag3"); - - @BeforeEach - void setUp() { - maker1 = makerRepository.save(MakerFixture.maker() - .id(makerId1) - .name(name) - .job(job) - .profileImageUrl(profileImageUrl) - .content(content) - .themeId(themeId1) - .tags(tags) - .build() - ); - maker2 = makerRepository.save(MakerFixture.maker() - .id(makerId2) - .name(name) - .job(job) - .profileImageUrl(profileImageUrl) - .content(content) - .themeId(themeId2) - .tags(tags) - .build() - ); - - theme1 = themeRepository.save(ThemeFixture.theme().id(themeId1).name("테마 1").build()); - theme2 = themeRepository.save(ThemeFixture.theme().id(themeId2).name("테마 2").build()); - } - - @Test - @DisplayName("[성공] 메이커와 해당하는 테마 정보를 조회한다.") - void acquireAll() { - // given, when - MakerListAcquireServiceResponse actual = makerService.acquireAll(); - - // then - assertThat(actual.makers()).hasSize(2); - assertThat(actual.makers().stream().filter(maker -> maker.makerId() == makerId1).findAny()).isNotEmpty(); - assertThat(actual.makers().stream().filter(maker -> maker.makerId() == makerId2).findAny()).isNotEmpty(); - } - } -} diff --git a/src/test/java/com/soptie/server/member/service/MemberServiceImplTest.java b/src/test/java/com/soptie/server/member/service/MemberServiceImplTest.java deleted file mode 100644 index ba21822e..00000000 --- a/src/test/java/com/soptie/server/member/service/MemberServiceImplTest.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.soptie.server.member.service; - -import static com.soptie.server.doll.entity.DollType.*; -import static com.soptie.server.member.message.ErrorCode.*; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.List; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.soptie.server.conversation.adapter.ConversationFinder; -import com.soptie.server.conversation.entity.Conversation; -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.member.entity.CottonType; -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.exception.MemberException; -import com.soptie.server.member.service.dto.request.CottonGiveServiceRequest; -import com.soptie.server.member.service.dto.request.MemberHomeInfoGetServiceRequest; -import com.soptie.server.member.service.dto.response.MemberHomeInfoGetServiceResponse; -import com.soptie.server.memberdoll.entity.MemberDoll; -import com.soptie.server.support.fixture.ConversationFixture; -import com.soptie.server.support.fixture.DollFixture; -import com.soptie.server.support.fixture.MemberDollFixture; -import com.soptie.server.support.fixture.MemberFixture; - -@ExtendWith(MockitoExtension.class) -class MemberServiceImplTest { - - @InjectMocks - private MemberServiceImpl memberService; - - @Mock - private MemberFinder memberFinder; - - @Mock - private ConversationFinder conversationFinder; -/* - @Test - @DisplayName("멤버 프로필 생성 시, 멤버 데일리 루틴 생성과 멤버 인형 생성 메소드를 호출한다.") - void 멤버_프로필을_생성하면서_멤버_데일리_루틴과_멤버_인형을_생성한다() { - // given - long memberId = 1L; - Member member = member(memberId); - DollType dollType = BROWN; - String name = "memberDoll"; - List routines = List.of(2L, 3L, 4L); - MemberProfileCreateRequest request = new MemberProfileCreateRequest(dollType, name, routines); - doNothing().when(memberRoutineSaver).checkHasDeletedAndSave(member, List.of(2L, 3L, 4L)); - doNothing().when(memberService).createMemberDoll(member, dollType, name); - - // when - memberService.createMemberProfile(MemberProfileCreateServiceRequest.of(memberId, request)); - - // then - verify(memberService).createDailyRoutines(member, routines); - verify(memberService).createMemberDoll(member, dollType, name); - }*/ - - @Test - @DisplayName("솜뭉치 개수가 양수일 때 솜뭉치를 줄 수 있다.") - void canGiveCottonWhenCottonCountIsPositive() { - // given - long memberId = 1L; - MemberDoll memberDoll = new MemberDoll(1L); - Member member = member(memberId, memberDoll, 1); - int beforeCotton = member.getCottonInfo().getDailyCottonCount(); - - // when - memberService.giveCotton(CottonGiveServiceRequest.of(member.getId(), CottonType.DAILY)); - - // then - assertThat(member.getCottonInfo().getDailyCottonCount()).isEqualTo(beforeCotton - 1); - } - - @Test - @DisplayName("솜뭉치 개수가 0일 때 솜뭉치를 주려 하면 예외가 발생한다.") - void occurExceptionGiveCottonWhenCottonCountIsZero() { - // given - long memberId = 1L; - MemberDoll memberDoll = new MemberDoll(1L); - Member member = member(memberId, memberDoll); - - // when, then - assertThatThrownBy( - () -> memberService.giveCotton(CottonGiveServiceRequest.of(member.getId(), CottonType.DAILY))) - .isInstanceOf(MemberException.class) - .hasMessage("[MemberException] : " + NOT_ENOUGH_COTTON.getMessage()); - } - - @Test - @DisplayName("멤버의 멤버 인형 정보와 솜뭉치 개수를 가져온다.") - void acquireProfile() { - // given - long dollId = 1L; - Doll doll = doll(dollId, BROWN, "faceImageUrl"); - long memberDollId = 2L; - MemberDoll memberDoll = memberDoll(memberDollId, "memberDoll", 0, doll); - long memberId = 3L; - Member member = member(memberId, memberDoll); - List conversationIds = List.of(1L, 2L); - List conversations = conversations(conversationIds); - - // when - MemberHomeInfoGetServiceResponse result = memberService.getMemberHomeInfo( - MemberHomeInfoGetServiceRequest.of(memberId)); - - // then - assertThat(MemberHomeInfoGetServiceResponse.of(member, - conversations.stream().map(Conversation::getContent).toList())).isEqualTo(result); - } - - private Member member(long memberId) { - Member member = MemberFixture.member().id(memberId).build(); - doReturn(member).when(memberFinder).findById(memberId); - return member; - } - - private Member member(long memberId, MemberDoll memberDoll) { - Member member = MemberFixture.member().id(memberId).memberDoll(memberDoll).build(); - doReturn(member).when(memberFinder).findById(memberId); - return member; - } - - private Member member(long memberId, MemberDoll memberDoll, int dailyCottonCount) { - Member member = MemberFixture.member() - .id(memberId) - .memberDoll(memberDoll) - .dailyCotton(dailyCottonCount) - .build(); - doReturn(member).when(memberFinder).findById(memberId); - return member; - } - - private MemberDoll memberDoll(long memberDollId, String name, int happinessCottonCount, Doll doll) { - MemberDoll memberDoll = MemberDollFixture.memberDoll().id(memberDollId).name(name) - .happinessCottonCount(happinessCottonCount).doll(doll).build(); - return memberDoll; - } - - private Doll doll(Long id, DollType dollType, String faceImageUrl) { - Doll doll = DollFixture.doll().id(id).dollType(dollType).faceImageUrl(faceImageUrl).build(); - return doll; - } - - private List conversations(List conversationIds) { - List conversations = conversationIds.stream() - .map(conversationId -> ConversationFixture.conversation() - .id(conversationId) - .content("conversation" + conversationId) - .build() - ).toList(); - doReturn(conversations).when(conversationFinder).findAll(); - return conversations; - } -} diff --git a/src/test/java/com/soptie/server/member/service/integration/MemberServiceIntegrationTest.java b/src/test/java/com/soptie/server/member/service/integration/MemberServiceIntegrationTest.java deleted file mode 100644 index cef4914c..00000000 --- a/src/test/java/com/soptie/server/member/service/integration/MemberServiceIntegrationTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.soptie.server.member.service.integration; - -import static com.soptie.server.doll.entity.DollType.*; -import static com.soptie.server.routine.entity.RoutineType.*; -import static org.assertj.core.api.Assertions.*; - -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.doll.entity.DollType; -import com.soptie.server.doll.repository.DollRepository; -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.member.controller.dto.request.MemberProfileCreateRequest; -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.repository.MemberRepository; -import com.soptie.server.member.service.MemberServiceImpl; -import com.soptie.server.member.service.dto.request.MemberProfileCreateServiceRequest; -import com.soptie.server.memberroutine.adapter.MemberRoutineFinder; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.repository.RoutineRepository; -import com.soptie.server.support.IntegrationTest; -import com.soptie.server.support.fixture.DollFixture; -import com.soptie.server.support.fixture.MemberFixture; -import com.soptie.server.support.fixture.RoutineFixture; -import com.soptie.server.support.fixture.ThemeFixture; -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.repository.ThemeRepository; - -@IntegrationTest -@Transactional -public class MemberServiceIntegrationTest { - - @Autowired - private MemberServiceImpl memberService; - - @Autowired - private MemberFinder memberFinder; - - @Autowired - private MemberRepository memberRepository; - - @Autowired - private RoutineRepository routineRepository; - - @Autowired - private ThemeRepository themeRepository; - - @Autowired - private DollRepository dollRepository; - - @Autowired - private MemberRoutineFinder memberRoutineFinder; - - @SuppressWarnings("checkstyle:TypeName") - @Nested - class Create { - - Member member; - DollType dollType = BROWN; - Routine routine; - - @BeforeEach - void setUp() { - member = memberRepository.save(MemberFixture.member().build()); - Theme theme = themeRepository.save(ThemeFixture.theme().name("theme").build()); - dollRepository.save(DollFixture.doll().dollType(dollType).build()); - routine = routineRepository.save( - RoutineFixture.routine().content("content").type(DAILY).theme(theme).build()); - } - - @Test - @DisplayName("[성공] 응답이 유효하면 회원 프로필이 생성된다.") - void registerProfile() { - // given - String name = "doll"; - List routines = List.of(routine.getId()); - MemberProfileCreateRequest controllerRequest = new MemberProfileCreateRequest(dollType, name, routines); - MemberProfileCreateServiceRequest request = MemberProfileCreateServiceRequest.of(member.getId(), - controllerRequest); - - // when - memberService.createMemberProfile(request); - - // then - Member foundMember = memberFinder.findById(member.getId()); - assertThat(foundMember.getMemberDoll().getDoll().getDollType()).isEqualTo(dollType); - assertThat(foundMember.getMemberDoll().getName()).isEqualTo(name); - assertThat(memberRoutineFinder.findAllByMember(foundMember).size()).isEqualTo(routines.size()); - assertThat(memberRoutineFinder.findAllByMember(foundMember).get(0).id()).isEqualTo(routine.getId()); - } - } -} diff --git a/src/test/java/com/soptie/server/memberdoll/service/MemberDollServiceImplTest.java b/src/test/java/com/soptie/server/memberdoll/service/MemberDollServiceImplTest.java deleted file mode 100644 index b1ab8448..00000000 --- a/src/test/java/com/soptie/server/memberdoll/service/MemberDollServiceImplTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.soptie.server.memberdoll.service; - -import static com.soptie.server.doll.entity.DollType.*; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.Optional; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.doll.repository.DollRepository; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberdoll.repository.MemberDollRepository; -import com.soptie.server.support.fixture.MemberFixture; - -@ExtendWith(MockitoExtension.class) -class MemberDollServiceImplTest { - - @InjectMocks - private MemberDollServiceImpl memberDollService; - - @Mock - private DollRepository dollRepository; - - @Mock - private MemberDollRepository memberDollRepository; - - @Test - @DisplayName("멤버 인형을 생성하고 이를 멤버의 멤버 인형으로 설정한다.") - void addMemberDoll() { - // given - long id = 1L; - String name = "brownie"; - Member member = member(id); - doReturn(Optional.of(new Doll())).when(dollRepository).findByDollType(BROWN); - - // when - memberDollService.createMemberDoll(member, BROWN, name); - - // then - assertThat(member.getMemberDoll().getName()).isEqualTo(name); - } - - private Member member(long memberId) { - Member member = MemberFixture.member().id(memberId).build(); - return member; - } -} diff --git a/src/test/java/com/soptie/server/memberroutine/service/MemberRoutineServiceTest.java b/src/test/java/com/soptie/server/memberroutine/service/MemberRoutineServiceTest.java deleted file mode 100644 index a1e4f4a3..00000000 --- a/src/test/java/com/soptie/server/memberroutine/service/MemberRoutineServiceTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.soptie.server.memberroutine.service; - -import static com.soptie.server.routine.entity.RoutineType.*; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.List; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.adapter.MemberRoutineDeleter; -import com.soptie.server.memberroutine.adapter.MemberRoutineFinder; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.memberroutine.service.dto.request.MemberRoutineAchieveServiceRequest; -import com.soptie.server.support.fixture.MemberFixture; -import com.soptie.server.support.fixture.MemberRoutineFixture; - -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@ExtendWith(MockitoExtension.class) -class MemberRoutineServiceTest { - - @InjectMocks - private MemberRoutineUpdateService memberRoutineUpdateService; - - @Mock - private MemberFinder memberFinder; - - @Mock - private MemberRoutineFinder memberRoutineFinder; - - @Mock - private MemberRoutineDeleter memberRoutineDeleter; - - @Test - @DisplayName("[성공] 데일리 루틴을 달성하면 달성 횟수와 데일리 솜 뭉치 개수가 1만큼 증가한다.") - void shouldUpdateAchieveCountAndCottonCountWhenAchieveDailyRoutine() { - // given - int beforeCottonCount = 0; - int beforeAchieveCount = 0; - - Member member = MemberFixture.member().id(1L).dailyCotton(beforeCottonCount).build(); - MemberRoutine memberRoutine = MemberRoutineFixture.memberRoutine() - .id(3L) - .type(DAILY) - .isAchieve(false) - .achieveCount(beforeAchieveCount) - .member(member) - .build(); - - doReturn(member).when(memberFinder).findById(member.getId()); - doReturn(memberRoutine).when(memberRoutineFinder).findById(memberRoutine.getId()); - - MemberRoutineAchieveServiceRequest request = MemberRoutineAchieveServiceRequest.of(member.getId(), - memberRoutine.getId()); - - // when - memberRoutineUpdateService.updateAchievementStatus(request); - - // then - assertThat(memberRoutine.isAchieve()).isTrue(); - assertThat(memberRoutine.getAchieveCount()).isEqualTo(beforeAchieveCount + 1); - assertThat(member.getCottonInfo().getDailyCottonCount()).isEqualTo(beforeCottonCount + 1); - } - - @Test - @DisplayName("[성공] 행복 루틴을 달성하면 달성 횟수와 행복 솜 뭉치 개수가 1만큼 증가한다.") - void shouldUpdateAchieveCountAndCottonCountWhenAchieveHappinessRoutine() { - // given - int beforeCottonCount = 0; - int beforeAchieveCount = 0; - - Member member = MemberFixture.member().id(1L).dailyCotton(beforeCottonCount).build(); - MemberRoutine memberRoutine = MemberRoutineFixture.memberRoutine() - .id(3L) - .type(CHALLENGE) - .isAchieve(false) - .achieveCount(beforeAchieveCount) - .member(member) - .build(); - - doReturn(member).when(memberFinder).findById(member.getId()); - doReturn(memberRoutine).when(memberRoutineFinder).findById(memberRoutine.getId()); - doNothing().when(memberRoutineDeleter).softDelete(memberRoutine); - - MemberRoutineAchieveServiceRequest request = MemberRoutineAchieveServiceRequest.of(member.getId(), - memberRoutine.getId()); - - // when - memberRoutineUpdateService.updateAchievementStatus(request); - - // then - assertThat(memberRoutine.isAchieve()).isTrue(); - assertThat(memberRoutine.getAchieveCount()).isEqualTo(beforeAchieveCount + 1); - assertThat(member.getCottonInfo().getHappinessCottonCount()).isEqualTo(beforeCottonCount + 1); - } - - @Test - @DisplayName("[성공] 달성한 데일리 루틴을 달성 초기화한다.") - void updateAchieveFalseAchievedMemberRoutine() { - // given - List memberRoutines = List.of( - MemberRoutineFixture.memberRoutine().id(1L).isAchieve(true).build(), - MemberRoutineFixture.memberRoutine().id(2L).isAchieve(true).build()); - - doReturn(memberRoutines).when(memberRoutineFinder).findAchieved(); - - // when - memberRoutineUpdateService.initDailyRoutines(); - - // then - assertThat(memberRoutines.get(0).isAchieve()).isFalse(); - assertThat(memberRoutines.get(1).isAchieve()).isFalse(); - } - -} diff --git a/src/test/java/com/soptie/server/memberroutine/service/integration/MemberRoutineServiceIntegrationTest.java b/src/test/java/com/soptie/server/memberroutine/service/integration/MemberRoutineServiceIntegrationTest.java deleted file mode 100644 index b6d3dea6..00000000 --- a/src/test/java/com/soptie/server/memberroutine/service/integration/MemberRoutineServiceIntegrationTest.java +++ /dev/null @@ -1,462 +0,0 @@ -package com.soptie.server.memberroutine.service.integration; - -import static com.soptie.server.routine.entity.RoutineType.CHALLENGE; -import static com.soptie.server.routine.entity.RoutineType.DAILY; -import static com.soptie.server.routine.message.RoutineErrorCode.CANNOT_ADD_MEMBER_ROUTINE; -import static com.soptie.server.routine.message.RoutineErrorCode.DUPLICATED_ROUTINE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import java.util.List; -import java.util.Optional; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.repository.MemberRepository; -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberDailyRoutineCreateRequest; -import com.soptie.server.memberroutine.controller.v1.dto.request.MemberHappinessRoutineRequest; -import com.soptie.server.memberroutine.entity.DeletedMemberRoutine; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.memberroutine.repository.DeletedMemberRoutineRepository; -import com.soptie.server.memberroutine.repository.MemberRoutineRepository; -import com.soptie.server.memberroutine.service.MemberRoutineCreateService; -import com.soptie.server.memberroutine.service.MemberRoutineDeleteService; -import com.soptie.server.memberroutine.service.MemberRoutineReadService; -import com.soptie.server.memberroutine.service.dto.request.MemberChallengeRoutineAcquireServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberDailyRoutineCreateServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberDailyRoutineListAcquireServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberHappinessRoutineCreateServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberHappinessRoutineGetServiceRequest; -import com.soptie.server.memberroutine.service.dto.request.MemberRoutinesDeleteServiceRequest; -import com.soptie.server.memberroutine.service.dto.response.MemberChallengeRoutineAcquireServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutineListAcquireServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutinesAcquireServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberDailyRoutinesAcquireServiceResponse.MemberDailyRoutineServiceResponse; -import com.soptie.server.memberroutine.service.dto.response.MemberHappinessRoutineGetServiceResponse; -import com.soptie.server.routine.entity.Challenge; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.exception.RoutineException; -import com.soptie.server.routine.repository.ChallengeRepository; -import com.soptie.server.routine.repository.RoutineRepository; -import com.soptie.server.support.IntegrationTest; -import com.soptie.server.support.fixture.ChallengeFixture; -import com.soptie.server.support.fixture.MemberFixture; -import com.soptie.server.support.fixture.MemberRoutineFixture; -import com.soptie.server.support.fixture.RoutineFixture; -import com.soptie.server.support.fixture.ThemeFixture; -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.repository.ThemeRepository; - -@IntegrationTest -@Transactional -public class MemberRoutineServiceIntegrationTest { - - @Autowired - MemberRoutineCreateService memberRoutineCreateService; - - @Autowired - MemberRoutineReadService memberRoutineReadService; - - @Autowired - MemberRoutineDeleteService memberRoutineDeleteService; - - @Autowired - MemberRepository memberRepository; - - @Autowired - RoutineRepository routineRepository; - - @Autowired - MemberRoutineRepository memberRoutineRepository; - - @Autowired - DeletedMemberRoutineRepository deletedMemberRoutineRepository; - - @Autowired - ThemeRepository themeRepository; - - @Autowired - ChallengeRepository challengeRepository; - - @Nested - class Add { - - Member member; - Routine routine; - Challenge challenge; - - @BeforeEach - void setUp() { - member = memberRepository.save(MemberFixture.member().build()); - routine = routineRepository.save(RoutineFixture.routine().build()); - challenge = challengeRepository.save(ChallengeFixture.challenge().build()); - } - - @Test - @DisplayName("[성공] 삭제한 적 없는 데일리 루틴을 추가한다.") - void createHasNotDeletedDailyRoutine() { - // given - MemberDailyRoutineCreateServiceRequest request = MemberDailyRoutineCreateServiceRequest.of(member.getId(), - new MemberDailyRoutineCreateRequest(routine.getId())); - - // when - memberRoutineCreateService.createDailyRoutine(request); - - // then - assertThat(memberRoutineRepository.existsByMemberAndTypeAndRoutineId(member, routine.getType(), - routine.getId())).isTrue(); - } - - @Test - @DisplayName("[성공] 삭제한 적 있는 데일리 루틴을 추가한디.") - void createHasDeletedDailyRoutine() { - // given - MemberRoutine memberRoutine = MemberRoutineFixture.memberRoutine() - .isAchieve(true) - .achieveCount(5) - .type(routine.getType()) - .routineId(routine.getId()) - .member(member) - .build(); - - saveAndDelete(memberRoutine); - - MemberDailyRoutineCreateServiceRequest request = MemberDailyRoutineCreateServiceRequest.of(member.getId(), - new MemberDailyRoutineCreateRequest(routine.getId())); - - // when - memberRoutineCreateService.createDailyRoutine(request); - - // then - final MemberRoutine found = memberRoutineRepository.findByMemberAndTypeAndRoutineId(member, - routine.getType(), routine.getId()).orElseThrow(RuntimeException::new); - - assertThat(found.isAchieve()).isTrue(); - assertThat(found.getAchieveCount()).isEqualTo(memberRoutine.getAchieveCount()); - } - - @Test - @DisplayName("[예외] 가지고 있는 데일리 루틴은 추가할 수 없다.") - void cannotCreateDailyRoutineIfAlreadyHave() { - // given - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .type(routine.getType()) - .routineId(routine.getId()) - .member(member) - .build()); - - MemberDailyRoutineCreateServiceRequest request = MemberDailyRoutineCreateServiceRequest.of(member.getId(), - new MemberDailyRoutineCreateRequest(routine.getId())); - - // when & then - assertThatThrownBy(() -> memberRoutineCreateService.createDailyRoutine(request)).isInstanceOf( - RoutineException.class).hasMessage("[RoutineException] : " + DUPLICATED_ROUTINE.getMessage()); - } - - @Test - @DisplayName("[성공] 삭제한 적 없는 행복 루틴을 추가한다.") - void createHasNotDeletedHappinessRoutine() { - // given - MemberHappinessRoutineCreateServiceRequest request = MemberHappinessRoutineCreateServiceRequest.of( - member.getId(), new MemberHappinessRoutineRequest(challenge.getId())); - - // when - memberRoutineCreateService.createHappinessRoutine(request); - - // then - assertThat(memberRoutineRepository.existsByMemberAndTypeAndRoutineId(member, CHALLENGE, - challenge.getId())).isTrue(); - } - - @Test - @DisplayName("[성공] 삭제한 적 있는 행복 루틴을 추가한디.") - void createHasDeletedHappinessRoutine() { - // given - MemberRoutine memberRoutine = MemberRoutineFixture.memberRoutine() - .isAchieve(true) - .achieveCount(5) - .type(CHALLENGE) - .routineId(challenge.getId()) - .member(member) - .build(); - - saveAndDelete(memberRoutine); - - MemberHappinessRoutineCreateServiceRequest request = MemberHappinessRoutineCreateServiceRequest.of( - member.getId(), new MemberHappinessRoutineRequest(challenge.getId())); - - // when - memberRoutineCreateService.createHappinessRoutine(request); - - // then - final MemberRoutine found = memberRoutineRepository.findByMemberAndTypeAndRoutineId(member, CHALLENGE, - challenge.getId()).orElseThrow(RuntimeException::new); - - assertThat(found.isAchieve()).isTrue(); - assertThat(found.getAchieveCount()).isEqualTo(memberRoutine.getAchieveCount()); - } - - @Test - @DisplayName("[예외] 도전 루틴은 최대 1개까지 가질 수 있다.") - void cannotCreateChallengeRoutineIfAlreadyHaveOne() { - // given - Challenge challenge2 = challengeRepository.save(ChallengeFixture.challenge().build()); - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .type(CHALLENGE) - .routineId(challenge2.getId()) - .member(member) - .build()); - - MemberHappinessRoutineCreateServiceRequest request = MemberHappinessRoutineCreateServiceRequest.of( - member.getId(), new MemberHappinessRoutineRequest(challenge.getId())); - - // when & then - assertThatThrownBy(() -> memberRoutineCreateService.createHappinessRoutine(request)).isInstanceOf( - RoutineException.class).hasMessage("[RoutineException] : " + CANNOT_ADD_MEMBER_ROUTINE.getMessage()); - } - - private void saveAndDelete(MemberRoutine memberRoutine) { - MemberRoutine savedMemberRoutine = memberRoutineRepository.save(memberRoutine); - deletedMemberRoutineRepository.save(new DeletedMemberRoutine(savedMemberRoutine)); - memberRoutineRepository.delete(savedMemberRoutine); - } - - } - - @Nested - class Delete { - - Member member; - Routine routine; - MemberRoutine memberRoutine; - - @BeforeEach - void setUp() { - member = memberRepository.save(MemberFixture.member().build()); - routine = routineRepository.save(RoutineFixture.routine().build()); - memberRoutine = memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member) - .routineId(routine.getId()) - .type(routine.getType()) - .build()); - } - - @Test - @DisplayName("[성공] 회원이 가진 데일리 루틴을 삭제한다.") - void deleteMemberDailyRoutines() { - // given - MemberRoutinesDeleteServiceRequest request = MemberRoutinesDeleteServiceRequest.of(member.getId(), - List.of(memberRoutine.getId())); - - // when - memberRoutineDeleteService.deleteMemberRoutines(request); - - // then - assertThat(memberRoutineRepository.existsByMemberAndTypeAndRoutineId(member, routine.getType(), - routine.getId())).isFalse(); - assertThat(deletedMemberRoutineRepository.existsByMemberAndTypeAndRoutineId(member, routine.getType(), - routine.getId())).isTrue(); - } - } - - @Nested - class Acquire { - - Member member1; - Member member2; - Theme theme1; - Theme theme2; - Routine routine1; - Routine routine2; - Routine routine3; - Routine challengeRoutine; - - @BeforeEach - void setUp() { - member1 = memberRepository.save(MemberFixture.member().build()); - member2 = memberRepository.save(MemberFixture.member().build()); - - theme1 = themeRepository.save(ThemeFixture.theme().name("테마 1").build()); - theme2 = themeRepository.save(ThemeFixture.theme().name("테마 2").build()); - - routine1 = routineRepository.save( - RoutineFixture.routine().theme(theme1).type(DAILY).content("새로운 나").build()); - routine2 = routineRepository.save( - RoutineFixture.routine().theme(theme1).type(DAILY).content("깨끗한 나").build()); - routine3 = routineRepository.save( - RoutineFixture.routine().theme(theme2).type(DAILY).content("똑똑한 나").build()); - challengeRoutine = routineRepository.save( - RoutineFixture.routine().theme(theme1).type(CHALLENGE).content("도전 루틴").build()); - } - - @Test - @DisplayName("[성공] 회원이 가진 모든 데일리 루틴을 조회한다.") - void getMemberDailyRoutinesByMember() { - // given - MemberRoutine memberRoutine1 = memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member1) - .routineId(routine1.getId()) - .type(routine1.getType()) - .build()); - MemberRoutine memberRoutine2 = memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member1) - .routineId(routine2.getId()) - .type(routine2.getType()) - .build()); - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member2) - .routineId(routine3.getId()) - .type(routine3.getType()) - .build()); - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member1) - .routineId(challengeRoutine.getId()) - .type(challengeRoutine.getType()) - .build()); - - MemberDailyRoutineListAcquireServiceRequest request = MemberDailyRoutineListAcquireServiceRequest.of( - member1.getId()); - - // when - final MemberDailyRoutinesAcquireServiceResponse actual = memberRoutineReadService.getDailyRoutines(request); - - // then - List contents = actual.routines().stream().map(MemberDailyRoutineServiceResponse::content).toList(); - assertThat(contents).hasSize(2); - assertThat(contents).containsExactlyInAnyOrder(routine1.getContent(), routine2.getContent()); - - List memberRoutineIds = actual.routines() - .stream() - .map(MemberDailyRoutineServiceResponse::routineId) - .toList(); - assertThat(memberRoutineIds).containsExactlyInAnyOrder(memberRoutine1.getRoutineId(), - memberRoutine2.getId()); - } - - @Test - @DisplayName("[성공] 회원이 가진 행복 루틴을 조회할 수 있다.") - void getMemberHappinessRoutine() { - // given - Challenge challenge = challengeRepository.save( - ChallengeFixture.challenge() - .content("무한~ 도전~") - .description("무한으로 즐겨요") - .requiredTime("2시간") - .place("MBC") - .routine(challengeRoutine) - .build()); - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member1) - .type(CHALLENGE) - .routineId(challenge.getId()) - .build()); - - MemberHappinessRoutineGetServiceRequest request = MemberHappinessRoutineGetServiceRequest.of( - member1.getId()); - - // when - final Optional actual = memberRoutineReadService - .getHappinessRoutine(request); - - // then - assertThat(actual).isPresent(); - - final MemberHappinessRoutineGetServiceResponse response = actual.get(); - assertThat(response.content()).isEqualTo(challenge.getContent()); - assertThat(response.description()).isEqualTo(challenge.getDescription()); - } - - @Test - @DisplayName("[성공] 회원이 가진 행복 루틴이 없으면 빈 값으로 조회된다.") - void getEmptyWhenMemberHasNotHappinessRoutine() { - // given - MemberHappinessRoutineGetServiceRequest request = MemberHappinessRoutineGetServiceRequest.of( - member1.getId()); - - // when - final Optional actual = memberRoutineReadService - .getHappinessRoutine(request); - - // then - assertThat(actual).isEmpty(); - } - - @Test - @DisplayName("[성공] 회원이 가진 모든 데일리 루틴을 테마별로 조회한다. 이 때, 루틴은 가나다순으로 정렬된다.") - void acquireAllByMember() { - // given - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member1).routineId(routine1.getId()).type(routine1.getType()).build()); - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member1).routineId(routine2.getId()).type(routine2.getType()).build()); - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member1).routineId(routine3.getId()).type(routine3.getType()).build()); - - MemberDailyRoutineListAcquireServiceRequest request = MemberDailyRoutineListAcquireServiceRequest.of( - member1.getId()); - - // when - final MemberDailyRoutineListAcquireServiceResponse actual = memberRoutineReadService.acquireAll(request); - - // then - int themeCount = actual.routines().size(); - assertThat(themeCount).isEqualTo(2); - List contents = actual.routines().get(0).routines().stream().map( - MemberDailyRoutinesAcquireServiceResponse.MemberDailyRoutineServiceResponse::content).toList(); - assertThat(contents).hasSize(2); - assertThat(contents).containsExactly(routine2.getContent(), routine1.getContent()); - } - - @Test - @DisplayName("[성공] 회원의 도전 루틴이 존재한다면 해당 도전 루틴을 테마와 함께 조회한다.") - void acquireByMember() { - // given - Challenge challenge = challengeRepository.save( - ChallengeFixture.challenge() - .content("무한~ 도전~") - .description("무한으로 즐겨요") - .requiredTime("2시간") - .place("MBC") - .routine(challengeRoutine) - .build()); - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .member(member1).routineId(challenge.getId()).type(challengeRoutine.getType()).build()); - - MemberChallengeRoutineAcquireServiceRequest request = - MemberChallengeRoutineAcquireServiceRequest.of(member1.getId()); - - // when - final Optional actual = - memberRoutineReadService.acquire(request); - - // then - assertThat(actual).isPresent(); - - final MemberChallengeRoutineAcquireServiceResponse response = actual.get(); - assertThat(response.theme().themeId()).isEqualTo(challenge.getRoutine().getTheme().getId()); - assertThat(response.theme().name()).isEqualTo(challenge.getRoutine().getTheme().getName()); - assertThat(response.content()).isEqualTo(challenge.getContent()); - } - - @Test - @DisplayName("[성공] 회원이 가진 도전 루틴이 없으면 빈 값으로 조회된다.") - void acquireEmptyWhenMemberHasNotChallengeRoutine() { - // given - MemberChallengeRoutineAcquireServiceRequest request = - MemberChallengeRoutineAcquireServiceRequest.of(member1.getId()); - - // when - final Optional actual = - memberRoutineReadService.acquire(request); - - // then - assertThat(actual).isEmpty(); - } - } -} diff --git a/src/test/java/com/soptie/server/routine/service/DailyRoutineServiceTest.java b/src/test/java/com/soptie/server/routine/service/DailyRoutineServiceTest.java deleted file mode 100644 index e2ca5d07..00000000 --- a/src/test/java/com/soptie/server/routine/service/DailyRoutineServiceTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.soptie.server.routine.service; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.List; -import java.util.Map; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.soptie.server.member.adapter.MemberFinder; -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.adapter.MemberRoutineFinder; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.routine.adapter.RoutineFinder; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; -import com.soptie.server.support.fixture.MemberFixture; -import com.soptie.server.support.fixture.MemberRoutineFixture; -import com.soptie.server.support.fixture.RoutineFixture; - -@ExtendWith(MockitoExtension.class) -class DailyRoutineServiceTest { - - @InjectMocks - RoutineService routineService; - - @Mock - RoutineFinder routineFinder; - - @Mock - MemberRoutineFinder memberRoutineFinder; - - @Mock - MemberFinder memberFinder; - - @Test - @DisplayName("[성공] 회원 루틴 유무에 따라 Map 타입으로 루틴 정보를 반환한다.") - void acquireRoutineToMember() { - // given - long themeId = 0L; - long memberId = 0L; - Member member = MemberFixture.member().build(); - List routines = List.of( - RoutineFixture.routine().id(1L).build(), - RoutineFixture.routine().id(2L).build(), - RoutineFixture.routine().id(3L).build(), - RoutineFixture.routine().id(4L).build(), - RoutineFixture.routine().id(5L).build() - ); - List memberRoutines = List.of( - MemberRoutineFixture.memberRoutine().routineId(1L).build(), - MemberRoutineFixture.memberRoutine().routineId(2L).build(), - MemberRoutineFixture.memberRoutine().routineId(3L).build() - ); - - doReturn(routines).when(routineFinder).findAllByTypeAndThemeId(RoutineType.DAILY, themeId); - doReturn(member).when(memberFinder).findById(memberId); - doReturn(memberRoutines).when(memberRoutineFinder).findAllByMemberAndType(member, RoutineType.DAILY); - - // when - Map> result = routineService.acquireAllInDailyByThemeAndMember(memberId, themeId); - - // then - assertThat(result.get(true)).hasSize(3); - assertThat(result.get(false)).hasSize(2); - } -} diff --git a/src/test/java/com/soptie/server/routine/service/integration/RoutineServiceIntegrationTest.java b/src/test/java/com/soptie/server/routine/service/integration/RoutineServiceIntegrationTest.java deleted file mode 100644 index df5ef10e..00000000 --- a/src/test/java/com/soptie/server/routine/service/integration/RoutineServiceIntegrationTest.java +++ /dev/null @@ -1,342 +0,0 @@ -package com.soptie.server.routine.service.integration; - -import static com.soptie.server.routine.entity.RoutineType.*; - -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.member.repository.MemberRepository; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.memberroutine.repository.MemberRoutineRepository; -import com.soptie.server.routine.entity.Challenge; -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; -import com.soptie.server.routine.repository.ChallengeRepository; -import com.soptie.server.routine.repository.RoutineRepository; -import com.soptie.server.routine.service.RoutineService; -import com.soptie.server.routine.service.dto.request.HappinessSubRoutineListGetServiceRequest; -import com.soptie.server.routine.service.dto.response.ChallengeRoutineListAcquireServiceResponse; -import com.soptie.server.routine.service.dto.response.HappinessSubRoutineListGetServiceResponse; -import com.soptie.server.routine.service.dto.response.HappinessSubRoutineListGetServiceResponse.HappinessSubRoutineServiceResponse; -import com.soptie.server.routine.service.vo.RoutineVO; -import com.soptie.server.support.IntegrationTest; -import com.soptie.server.support.fixture.ChallengeFixture; -import com.soptie.server.support.fixture.MemberFixture; -import com.soptie.server.support.fixture.MemberRoutineFixture; -import com.soptie.server.support.fixture.RoutineFixture; -import com.soptie.server.support.fixture.ThemeFixture; -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.repository.ThemeRepository; - -@IntegrationTest -@Transactional -public class RoutineServiceIntegrationTest { - - @Autowired - RoutineService routineService; - - @Autowired - RoutineRepository routineRepository; - - @Autowired - ThemeRepository themeRepository; - - @Autowired - MemberRepository memberRepository; - - @Autowired - MemberRoutineRepository memberRoutineRepository; - - @Autowired - ChallengeRepository challengeRepository; - - @Nested - class DailyRoutine { - - @Nested - class Acquire { - - Theme theme1; - Theme theme2; - Theme theme3; - - Routine routineOfTheme1; - Routine routineOfTheme2; - Routine routineOfTheme3; - - @BeforeEach - void setUp() { - theme1 = themeRepository.save(ThemeFixture.theme().name("관계 쌓기").build()); - theme2 = themeRepository.save(ThemeFixture.theme().name("한 걸음 성장").build()); - theme3 = themeRepository.save(ThemeFixture.theme().name("새로운 나").build()); - - routineOfTheme1 = routineRepository.save( - RoutineFixture.routine().type(RoutineType.DAILY).content("관계를 쌓아보자").theme(theme1).build()); - routineOfTheme2 = routineRepository.save( - RoutineFixture.routine().type(RoutineType.DAILY).content("성장하자").theme(theme2).build()); - routineOfTheme3 = routineRepository.save( - RoutineFixture.routine().type(RoutineType.DAILY).content("완전히 달라진 나").theme(theme3).build()); - } - - @Test - @DisplayName("[성공] 테마 id 목록에 포함된 테마를 갖는 데일리 루틴 목록을 조회한다.") - void acquireAllByThemeIds() { - // given - List themeIds = List.of(theme1.getId(), theme2.getId()); - - // when - final List actual = routineService.acquireAllInDailyByThemeIds(themeIds); - - // then - Assertions.assertThat(actual).hasSize(2); - List routineIds = actual.stream().map(RoutineVO::routineId).toList(); - Assertions.assertThat(routineIds) - .containsExactlyInAnyOrder(routineOfTheme1.getId(), routineOfTheme2.getId()); - } - - @Test - @DisplayName("[성공] 각 테마 id 별로 데일리 루틴 목록을 조회한다.") - void acquireAllWithThemeIds() { - // given - Set themeIds = new LinkedHashSet<>(); - themeIds.add(theme2.getId()); - themeIds.add(theme1.getId()); - - // when - final Map> actual = routineService.acquireAllInDailyWithThemeId(themeIds); - - // then - Assertions.assertThat(actual.keySet()).containsExactly(theme2.getId(), theme1.getId()); - - List routineIdsForTheme1 = actual.get(theme1.getId()).stream().map(Routine::getId).toList(); - Assertions.assertThat(routineIdsForTheme1).containsExactlyInAnyOrder(routineOfTheme1.getId()); - - List routineIdsForTheme2 = actual.get(theme2.getId()).stream().map(Routine::getId).toList(); - Assertions.assertThat(routineIdsForTheme2).containsExactlyInAnyOrder(routineOfTheme2.getId()); - } - - @Test - @DisplayName("[성공] 회원에게 없으면서, 주어진 테마에 속하는 데일리 루틴 목록을 조회한다.") - void acquireAllNotInMemberByThemeId() { - // given - Member member = memberRepository.save(MemberFixture.member().build()); - - Routine routineNotInMember1 = routineRepository.save(RoutineFixture.routine() - .type(RoutineType.DAILY).content("조회될 루틴1").theme(theme1).build()); - Routine routineNotInMember2 = routineRepository.save(RoutineFixture.routine() - .type(RoutineType.DAILY).content("조회될 루틴2").theme(theme1).build()); - - memberRoutineRepository.save(MemberRoutineFixture.memberRoutine() - .type(RoutineType.DAILY).routineId(routineOfTheme1.getId()).member(member).build()); - - // when - final List actual = routineService - .acquireAllInDailyNotInMemberByThemeId(member.getId(), theme1.getId()); - - // then - List routineIds = actual.stream().map(RoutineVO::routineId).toList(); - Assertions.assertThat(routineIds) - .containsExactlyInAnyOrder(routineNotInMember1.getId(), routineNotInMember2.getId()); - } - } - } - - @Nested - class AcquireHappinessRoutine { - - Routine routine1; - Routine routine2; - Routine routine3; - Theme theme1; - Theme theme2; - - @BeforeEach - void setUp() { - theme1 = themeRepository.save(ThemeFixture.theme().name("관계 쌓기").color("라일락").build()); - theme2 = themeRepository.save(ThemeFixture.theme().name("한 걸음 성장").color("민트").build()); - - routine1 = routineRepository.save( - RoutineFixture.routine().type(CHALLENGE).content("관계쌓는").theme(theme1).build()); - routine2 = routineRepository.save( - RoutineFixture.routine().type(CHALLENGE).content("성장하는").theme(theme1).build()); - routine3 = routineRepository.save( - RoutineFixture.routine().type(CHALLENGE).content("보여주는").theme(theme2).build()); - } - - @Test - @DisplayName("[성공] 테마에 포함된 행복 루틴 목록을 조회한다.") - void getHappinessRoutinesByTheme() { - // when - final List actual = routineService.acquireAllInHappinessByThemeId(theme1.getId()); - - // then - Assertions.assertThat(actual).hasSize(2); - List routineIds = actual.stream().map(Routine::getId).toList(); - Assertions.assertThat(routineIds).containsExactlyInAnyOrder(routine1.getId(), routine2.getId()); - } - } - - @Nested - class AcquireSubHappinessRoutine { - - Challenge challenge1; - Challenge challenge2; - Challenge challenge3; - Routine routine1; - Routine routine2; - Theme theme; - - @BeforeEach - void setUp() { - theme = themeRepository.save(ThemeFixture.theme().name("관계 쌓기").color("라일락").build()); - - routine1 = routineRepository.save( - RoutineFixture.routine().type(CHALLENGE).content("관계쌓는").theme(theme).build()); - routine2 = routineRepository.save( - RoutineFixture.routine().type(CHALLENGE).content("성장하는").theme(theme).build()); - - challenge1 = challengeRepository.save( - ChallengeFixture.challenge() - .content("도전 루틴 내용") - .description("도전 루틴 설명") - .requiredTime("10분") - .place("소프티 숙소") - .routine(routine1) - .build() - ); - challenge2 = challengeRepository.save( - ChallengeFixture.challenge() - .content("도전 루틴 내용") - .description("도전 루틴 설명") - .requiredTime("10분") - .place("소프티 숙소") - .routine(routine1) - .build() - ); - challenge3 = challengeRepository.save( - ChallengeFixture.challenge() - .content("도전 루틴 내용") - .description("도전 루틴 설명") - .requiredTime("10분") - .place("소프티 숙소") - .routine(routine2) - .build() - ); - } - - @Test - @DisplayName("[성공] 행복 루틴에 포함된 서브 루틴 목록을 조회한다.") - void getHappinessSubRoutinesByRoutine() { - // given - HappinessSubRoutineListGetServiceRequest request = HappinessSubRoutineListGetServiceRequest.of( - routine1.getId()); - - // when - final HappinessSubRoutineListGetServiceResponse actual = routineService.getHappinessSubRoutines(request); - - // then - Assertions.assertThat(actual.challenges()).hasSize(2); - - List challengeIds = actual.challenges().stream() - .map(HappinessSubRoutineServiceResponse::challengeId).toList(); - Assertions.assertThat(challengeIds).containsExactlyInAnyOrder(challenge1.getId(), challenge2.getId()); - } - } - - @Nested - class AcquireChallengeByThemes { - - Member member; - Challenge challenge1; - Challenge challenge2; - Challenge challenge3; - Routine routine1; - Routine routine2; - Theme theme; - MemberRoutine memberRoutine; - - @BeforeEach - void setUp() { - member = memberRepository.save(MemberFixture.member().build()); - theme = themeRepository.save(ThemeFixture.theme().name("관계 쌓기").color("라일락").build()); - - routine1 = routineRepository.save( - RoutineFixture.routine().type(CHALLENGE).content("관계쌓는").theme(theme).build()); - routine2 = routineRepository.save( - RoutineFixture.routine().type(CHALLENGE).content("성장하는").theme(theme).build()); - - challenge1 = challengeRepository.save( - ChallengeFixture.challenge().routine(routine1) - .content("선배 마라탕 사주세요.") - .description("혹시 탕후루도 같이?") - .requiredTime("30분") - .place("소프티 숙소") - .build() - ); - challenge2 = challengeRepository.save( - ChallengeFixture.challenge().routine(routine1) - .content("선배 탕후루 사주세요.") - .description("혹시 마라탕도 같이?") - .requiredTime("1시간") - .place("소프티 숙소") - .build() - ); - challenge3 = challengeRepository.save( - ChallengeFixture.challenge().routine(routine2) - .content("선배") - .description("안된다고요?") - .requiredTime("10분") - .place("소프티 숙소") - .build() - ); - - memberRoutine = memberRoutineRepository.save( - MemberRoutineFixture.memberRoutine() - .type(CHALLENGE).routineId(challenge2.getId()).member(member).build() - ); - } - - @Test - @DisplayName("[성공] 테마에 속한 도전 루틴 목록을 조회한다. 이 때, 멤버가 가지고 있는 도전 루틴이라면 hasRoutine의 값이 true이다.") - void acquireAllByTheme() { - // given - long themeId = theme.getId(); - long memberId = member.getId(); - - // when - final Map actual = - routineService.acquireAllInChallengeWithThemeId(memberId, themeId); - - // then - Assertions.assertThat(actual.keySet()) - .containsExactlyInAnyOrder(routine1.getContent(), routine2.getContent()); - - ChallengeRoutineListAcquireServiceResponse challenges = actual.get(routine1.getContent()); - Assertions.assertThat( - challenges.challenges().stream() - .filter(challenge -> challenge.challenge().challengeId() == challenge1.getId()) - .findAny() - .orElseThrow() - .hasRoutine() - ).isEqualTo(false); - Assertions.assertThat( - challenges.challenges().stream() - .filter(challenge -> challenge.challenge().challengeId() == challenge2.getId()) - .findAny() - .orElseThrow() - .hasRoutine() - ).isEqualTo(true); - } - } -} diff --git a/src/test/java/com/soptie/server/support/RepositoryTest.java b/src/test/java/com/soptie/server/support/RepositoryTest.java index 3144fe95..832174a9 100644 --- a/src/test/java/com/soptie/server/support/RepositoryTest.java +++ b/src/test/java/com/soptie/server/support/RepositoryTest.java @@ -8,8 +8,8 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; -import com.soptie.server.common.config.JpaAuditingConfig; -import com.soptie.server.common.config.JpaQueryFactoryConfig; +import com.soptie.server.persistence.config.JpaAuditingConfig; +import com.soptie.server.persistence.config.JpaQueryFactoryConfig; @DataJpaTest(showSql = false) @Import({JpaAuditingConfig.class, JpaQueryFactoryConfig.class}) diff --git a/src/test/java/com/soptie/server/support/fixture/ChallengeFixture.java b/src/test/java/com/soptie/server/support/fixture/ChallengeFixture.java deleted file mode 100644 index e27315b7..00000000 --- a/src/test/java/com/soptie/server/support/fixture/ChallengeFixture.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.soptie.server.support.fixture; - -import com.soptie.server.routine.entity.Challenge; -import com.soptie.server.routine.entity.Routine; - -public class ChallengeFixture { - - private Long id; - private String content = "널 방지용 내용 넣기"; - private String description; - private String requiredTime; - private String place; - private Routine routine; - - private ChallengeFixture() { - } - - public static ChallengeFixture challenge() { - return new ChallengeFixture(); - } - - public ChallengeFixture id(Long id) { - this.id = id; - return this; - } - - public ChallengeFixture content(String content) { - this.content = content; - return this; - } - - public ChallengeFixture description(String description) { - this.description = description; - return this; - } - - public ChallengeFixture requiredTime(String requiredTime) { - this.requiredTime = requiredTime; - return this; - } - - public ChallengeFixture place(String place) { - this.place = place; - return this; - } - - public ChallengeFixture routine(Routine routine) { - this.routine = routine; - return this; - } - - public Challenge build() { - return new Challenge(id, content, description, requiredTime, place, routine); - } -} diff --git a/src/test/java/com/soptie/server/support/fixture/ConversationFixture.java b/src/test/java/com/soptie/server/support/fixture/ConversationFixture.java deleted file mode 100644 index bf0682ba..00000000 --- a/src/test/java/com/soptie/server/support/fixture/ConversationFixture.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.soptie.server.support.fixture; - -import com.soptie.server.conversation.entity.Conversation; - -public class ConversationFixture { - - private Long id; - private String content; - - private ConversationFixture() { - } - - public static ConversationFixture conversation() { - return new ConversationFixture(); - } - - public ConversationFixture id(Long id) { - this.id = id; - return this; - } - - public ConversationFixture content(String content) { - this.content = content; - return this; - } - - public Conversation build() { - return new Conversation(id, content); - } -} diff --git a/src/test/java/com/soptie/server/support/fixture/DollFixture.java b/src/test/java/com/soptie/server/support/fixture/DollFixture.java deleted file mode 100644 index 4e38365d..00000000 --- a/src/test/java/com/soptie/server/support/fixture/DollFixture.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.soptie.server.support.fixture; - -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.doll.entity.DollType; - -public class DollFixture { - - private Long id; - private DollType dollType; - private String faceImageUrl; - - private DollFixture() { - } - - public static DollFixture doll() { - return new DollFixture(); - } - - public DollFixture id(Long id) { - this.id = id; - return this; - } - - public DollFixture dollType(DollType dollType) { - this.dollType = dollType; - return this; - } - - public DollFixture faceImageUrl(String faceImageUrl) { - this.faceImageUrl = faceImageUrl; - return this; - } - - public Doll build() { - return new Doll(id, dollType, faceImageUrl); - } -} diff --git a/src/test/java/com/soptie/server/support/fixture/MakerFixture.java b/src/test/java/com/soptie/server/support/fixture/MakerFixture.java deleted file mode 100644 index 189f43e0..00000000 --- a/src/test/java/com/soptie/server/support/fixture/MakerFixture.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.soptie.server.support.fixture; - -import java.util.List; - -import com.soptie.server.maker.entity.Maker; - -public class MakerFixture { - - private Long id; - private String name; - private String job; - private String profileImageUrl; - private String content; - private Long themeId; - private List tags; - - private MakerFixture() { - } - - public static MakerFixture maker() { - return new MakerFixture(); - } - - public MakerFixture id(Long id) { - this.id = id; - return this; - } - - public MakerFixture name(String name) { - this.name = name; - return this; - } - - public MakerFixture job(String job) { - this.job = job; - return this; - } - - public MakerFixture profileImageUrl(String profileImageUrl) { - this.profileImageUrl = profileImageUrl; - return this; - } - - public MakerFixture content(String content) { - this.content = content; - return this; - } - - public MakerFixture themeId(Long themeId) { - this.themeId = themeId; - return this; - } - - public MakerFixture tags(List tags) { - this.tags = tags; - return this; - } - - public Maker build() { - return new Maker(id, name, job, profileImageUrl, content, themeId, tags); - } -} diff --git a/src/test/java/com/soptie/server/support/fixture/MemberDollFixture.java b/src/test/java/com/soptie/server/support/fixture/MemberDollFixture.java deleted file mode 100644 index 681ac054..00000000 --- a/src/test/java/com/soptie/server/support/fixture/MemberDollFixture.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.soptie.server.support.fixture; - -import com.soptie.server.doll.entity.Doll; -import com.soptie.server.memberdoll.entity.MemberDoll; - -public class MemberDollFixture { - - private Long id; - private String name; - private int happinessCottonCount; - private Doll doll; - - public MemberDollFixture() { - } - - public static MemberDollFixture memberDoll() { - return new MemberDollFixture(); - } - - public MemberDollFixture id(Long id) { - this.id = id; - return this; - } - - public MemberDollFixture name(String name) { - this.name = name; - return this; - } - - public MemberDollFixture happinessCottonCount(int happinessCottonCount) { - this.happinessCottonCount = happinessCottonCount; - return this; - } - - public MemberDollFixture doll(Doll doll) { - this.doll = doll; - return this; - } - - public MemberDoll build() { - return new MemberDoll(id, name, happinessCottonCount, doll); - } -} diff --git a/src/test/java/com/soptie/server/support/fixture/MemberFixture.java b/src/test/java/com/soptie/server/support/fixture/MemberFixture.java deleted file mode 100644 index 0c2f62f7..00000000 --- a/src/test/java/com/soptie/server/support/fixture/MemberFixture.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.soptie.server.support.fixture; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberdoll.entity.MemberDoll; - -public class MemberFixture { - - private Long id; - private MemberDoll memberDoll; - private int dailyCottonCount = 0; - - private MemberFixture() { - } - - public static MemberFixture member() { - return new MemberFixture(); - } - - public MemberFixture id(Long id) { - this.id = id; - return this; - } - - public MemberFixture dailyCotton(int dailyCottonCount) { - this.dailyCottonCount = dailyCottonCount; - return this; - } - - public MemberFixture memberDoll(MemberDoll memberDoll) { - this.memberDoll = memberDoll; - return this; - } - - public Member build() { - return new Member(id, memberDoll, dailyCottonCount); - } -} diff --git a/src/test/java/com/soptie/server/support/fixture/MemberRoutineFixture.java b/src/test/java/com/soptie/server/support/fixture/MemberRoutineFixture.java deleted file mode 100644 index 92e183d9..00000000 --- a/src/test/java/com/soptie/server/support/fixture/MemberRoutineFixture.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.soptie.server.support.fixture; - -import com.soptie.server.member.entity.Member; -import com.soptie.server.memberroutine.entity.MemberRoutine; -import com.soptie.server.routine.entity.RoutineType; - -public class MemberRoutineFixture { - - private Long id; - private boolean isAchieve = false; - private int achieveCount = 0; - private RoutineType type; - private long routineId; - private Member member; - - private MemberRoutineFixture() { - } - - public static MemberRoutineFixture memberRoutine() { - return new MemberRoutineFixture(); - } - - public MemberRoutineFixture id(Long id) { - this.id = id; - return this; - } - - public MemberRoutineFixture isAchieve(boolean isAchieve) { - this.isAchieve = isAchieve; - return this; - } - - public MemberRoutineFixture achieveCount(int achieveCount) { - this.achieveCount = achieveCount; - return this; - } - - public MemberRoutineFixture type(RoutineType type) { - this.type = type; - return this; - } - - public MemberRoutineFixture routineId(long routineId) { - this.routineId = routineId; - return this; - } - - public MemberRoutineFixture member(Member member) { - this.member = member; - return this; - } - - public MemberRoutine build() { - return new MemberRoutine(id, isAchieve, achieveCount, type, routineId, member); - } -} diff --git a/src/test/java/com/soptie/server/support/fixture/RoutineFixture.java b/src/test/java/com/soptie/server/support/fixture/RoutineFixture.java deleted file mode 100644 index 48e3cd03..00000000 --- a/src/test/java/com/soptie/server/support/fixture/RoutineFixture.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.soptie.server.support.fixture; - -import com.soptie.server.routine.entity.Routine; -import com.soptie.server.routine.entity.RoutineType; -import com.soptie.server.theme.entity.Theme; - -public class RoutineFixture { - - private Long id; - private String content = "널 방지용 내용 넣기"; - private RoutineType type; - private Theme theme; - - private RoutineFixture() { - } - - public static RoutineFixture routine() { - return new RoutineFixture(); - } - - public RoutineFixture id(Long id) { - this.id = id; - return this; - } - - public RoutineFixture content(String content) { - this.content = content; - return this; - } - - public RoutineFixture type(RoutineType type) { - this.type = type; - return this; - } - - public RoutineFixture theme(Theme theme) { - this.theme = theme; - return this; - } - - public Routine build() { - return new Routine(id, content, type, theme); - } -} diff --git a/src/test/java/com/soptie/server/support/fixture/ThemeFixture.java b/src/test/java/com/soptie/server/support/fixture/ThemeFixture.java deleted file mode 100644 index b0ef8999..00000000 --- a/src/test/java/com/soptie/server/support/fixture/ThemeFixture.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.soptie.server.support.fixture; - -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.entity.ThemeImageLinks; -import com.soptie.server.theme.entity.ThemeType; - -public class ThemeFixture { - - private Long id; - private String name = "default"; - private String modifier = "default"; - private String description = "default"; - private String color = "#FFFFF"; - private ThemeType type = ThemeType.BASIC; - private final ThemeImageLinks imageLinks = new ThemeImageLinks("https://...", "https://...", "https://...", - "https://...", "https://..."); - - private ThemeFixture() { - } - - public static ThemeFixture theme() { - return new ThemeFixture(); - } - - public ThemeFixture id(Long id) { - this.id = id; - return this; - } - - public ThemeFixture name(String name) { - this.name = name; - return this; - } - - public ThemeFixture modifier(String modifier) { - this.modifier = modifier; - return this; - } - - public ThemeFixture description(String description) { - this.description = description; - return this; - } - - public ThemeFixture color(String color) { - this.color = color; - return this; - } - - public ThemeFixture type(ThemeType type) { - this.type = type; - return this; - } - - public Theme build() { - return new Theme(id, name, modifier, description, color, type, imageLinks); - } -} diff --git a/src/test/java/com/soptie/server/theme/service/integration/ThemeServiceIntegrationTest.java b/src/test/java/com/soptie/server/theme/service/integration/ThemeServiceIntegrationTest.java deleted file mode 100644 index ea0d70d6..00000000 --- a/src/test/java/com/soptie/server/theme/service/integration/ThemeServiceIntegrationTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.soptie.server.theme.service.integration; - -import static org.assertj.core.api.Assertions.*; - -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -import com.soptie.server.support.IntegrationTest; -import com.soptie.server.support.fixture.ThemeFixture; -import com.soptie.server.theme.entity.Theme; -import com.soptie.server.theme.entity.ThemeType; -import com.soptie.server.theme.repository.ThemeRepository; -import com.soptie.server.theme.service.ThemeService; -import com.soptie.server.theme.service.vo.ThemeVO; - -@IntegrationTest -@Transactional -public class ThemeServiceIntegrationTest { - - @Autowired - ThemeService themeService; - - @Autowired - ThemeRepository themeRepository; - - @Nested - class Acquire { - - List themes = List.of( - ThemeFixture.theme().type(ThemeType.BASIC).build(), - ThemeFixture.theme().type(ThemeType.BASIC).build(), - ThemeFixture.theme().type(ThemeType.BASIC).build(), - ThemeFixture.theme().type(ThemeType.MAKER).build(), - ThemeFixture.theme().type(ThemeType.MAKER).build() - ); - - @BeforeEach - void setUp() { - themeRepository.saveAll(themes); - } - - @Test - @DisplayName("[성공] BASIC 타입의 모든 테마 목록을 조회한다.") - void acquireAllInBasic() { - // given - long countOfBasic = themes.stream().filter(theme -> theme.getType().equals(ThemeType.BASIC)).count(); - - // when - List result = themeService.acquireAllInBasic(); - - // then - assertThat(result).hasSize((int)countOfBasic); - } - } -}