From 4d348a93d6b871be5ffff8e45b2935876ecc5bae Mon Sep 17 00:00:00 2001 From: yukyoungs Date: Mon, 27 Jul 2026 02:04:22 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[Feat]=20#39=20=EA=B3=84=EC=A0=95=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/AccountController.java | 35 +++++++++ .../domain/user/dto/AccountResponse.java | 13 ++++ .../domain/user/service/AccountService.java | 37 +++++++++ .../global/status/SuccessStatus.java | 7 +- .../user/service/AccountServiceTest.java | 76 +++++++++++++++++++ 5 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/leets7th/job_is_be/domain/user/controller/AccountController.java create mode 100644 src/main/java/com/leets7th/job_is_be/domain/user/dto/AccountResponse.java create mode 100644 src/main/java/com/leets7th/job_is_be/domain/user/service/AccountService.java create mode 100644 src/test/java/com/leets7th/job_is_be/domain/user/service/AccountServiceTest.java diff --git a/src/main/java/com/leets7th/job_is_be/domain/user/controller/AccountController.java b/src/main/java/com/leets7th/job_is_be/domain/user/controller/AccountController.java new file mode 100644 index 0000000..5121730 --- /dev/null +++ b/src/main/java/com/leets7th/job_is_be/domain/user/controller/AccountController.java @@ -0,0 +1,35 @@ +package com.leets7th.job_is_be.domain.user.controller; + +import com.leets7th.job_is_be.domain.user.dto.AccountResponse; +import com.leets7th.job_is_be.domain.user.service.AccountService; +import com.leets7th.job_is_be.global.response.ApiResponse; +import com.leets7th.job_is_be.global.status.SuccessStatus; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/settings/account") +@RequiredArgsConstructor +public class AccountController { + + private final AccountService accountService; + + @GetMapping + public ResponseEntity> getAccount( + @AuthenticationPrincipal Jwt jwt + ) { + return ApiResponse.success( + SuccessStatus.ACCOUNT_GET_SUCCESS, + accountService.getAccount(userId(jwt)) + ); + } + + private Long userId(Jwt jwt) { + return Long.valueOf(jwt.getSubject()); + } +} diff --git a/src/main/java/com/leets7th/job_is_be/domain/user/dto/AccountResponse.java b/src/main/java/com/leets7th/job_is_be/domain/user/dto/AccountResponse.java new file mode 100644 index 0000000..1dc838d --- /dev/null +++ b/src/main/java/com/leets7th/job_is_be/domain/user/dto/AccountResponse.java @@ -0,0 +1,13 @@ +package com.leets7th.job_is_be.domain.user.dto; + +import com.leets7th.job_is_be.domain.user.enums.SocialType; + +import java.time.LocalDateTime; + +public record AccountResponse( + SocialType socialType, + LocalDateTime joinedAt, + String receivingEmail, + boolean emailVerified +) { +} diff --git a/src/main/java/com/leets7th/job_is_be/domain/user/service/AccountService.java b/src/main/java/com/leets7th/job_is_be/domain/user/service/AccountService.java new file mode 100644 index 0000000..64780c8 --- /dev/null +++ b/src/main/java/com/leets7th/job_is_be/domain/user/service/AccountService.java @@ -0,0 +1,37 @@ +package com.leets7th.job_is_be.domain.user.service; + +import com.leets7th.job_is_be.domain.notification.entity.NotificationSetting; +import com.leets7th.job_is_be.domain.notification.repository.NotificationSettingRepository; +import com.leets7th.job_is_be.domain.user.dto.AccountResponse; +import com.leets7th.job_is_be.domain.user.entity.User; +import com.leets7th.job_is_be.domain.user.repository.UserRepository; +import com.leets7th.job_is_be.global.exception.GeneralException; +import com.leets7th.job_is_be.global.status.ErrorStatus; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class AccountService { + + private final UserRepository userRepository; + private final NotificationSettingRepository notificationSettingRepository; + + public AccountResponse getAccount(Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND)); + + boolean emailVerified = notificationSettingRepository.findByUser(user) + .map(NotificationSetting::isEmailVerified) + .orElse(false); + + return new AccountResponse( + user.getSocialType(), + user.getCreatedAt(), + user.getEmail(), + emailVerified + ); + } +} diff --git a/src/main/java/com/leets7th/job_is_be/global/status/SuccessStatus.java b/src/main/java/com/leets7th/job_is_be/global/status/SuccessStatus.java index 8449ac7..9a6dfa6 100644 --- a/src/main/java/com/leets7th/job_is_be/global/status/SuccessStatus.java +++ b/src/main/java/com/leets7th/job_is_be/global/status/SuccessStatus.java @@ -70,7 +70,12 @@ public enum SuccessStatus implements BaseStatus { NOTIFICATION_SETTING_GET_SUCCESS(HttpStatus.OK, "NOTIFICATION_200_1", "알림 수신 설정을 조회했습니다."), NOTIFICATION_SETTING_UPDATE_SUCCESS(HttpStatus.OK, "NOTIFICATION_200_2", "알림 수신 설정을 변경했습니다."), NOTIFICATION_SNOOZE_SUCCESS(HttpStatus.OK, "NOTIFICATION_200_3", "알림 발송을 스누즈 설정했습니다."), - NOTIFICATION_SNOOZE_CANCEL_SUCCESS(HttpStatus.OK, "NOTIFICATION_200_4", "알림 스누즈를 해제했습니다."); + NOTIFICATION_SNOOZE_CANCEL_SUCCESS(HttpStatus.OK, "NOTIFICATION_200_4", "알림 스누즈를 해제했습니다."), + + /** + * Account + */ + ACCOUNT_GET_SUCCESS(HttpStatus.OK, "ACCOUNT_200_1", "계정 정보를 조회했습니다."); private final HttpStatus httpStatus; private final String code; diff --git a/src/test/java/com/leets7th/job_is_be/domain/user/service/AccountServiceTest.java b/src/test/java/com/leets7th/job_is_be/domain/user/service/AccountServiceTest.java new file mode 100644 index 0000000..48c7df6 --- /dev/null +++ b/src/test/java/com/leets7th/job_is_be/domain/user/service/AccountServiceTest.java @@ -0,0 +1,76 @@ +package com.leets7th.job_is_be.domain.user.service; + +import com.leets7th.job_is_be.domain.notification.entity.NotificationSetting; +import com.leets7th.job_is_be.domain.notification.repository.NotificationSettingRepository; +import com.leets7th.job_is_be.domain.user.dto.AccountResponse; +import com.leets7th.job_is_be.domain.user.entity.User; +import com.leets7th.job_is_be.domain.user.enums.SocialType; +import com.leets7th.job_is_be.domain.user.repository.UserRepository; +import com.leets7th.job_is_be.global.exception.GeneralException; +import com.leets7th.job_is_be.global.status.ErrorStatus; +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 org.springframework.test.util.ReflectionTestUtils; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowableOfType; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class AccountServiceTest { + + @Mock + private UserRepository userRepository; + @Mock + private NotificationSettingRepository notificationSettingRepository; + + @InjectMocks + private AccountService accountService; + + private User user() { + User user = User.builder().socialId("s").socialType(SocialType.KAKAO).email("a@a.com").build(); + ReflectionTestUtils.setField(user, "id", 1L); + return user; + } + + @Test + void 사용자가_없으면_예외를_던진다() { + when(userRepository.findById(1L)).thenReturn(Optional.empty()); + + GeneralException exception = catchThrowableOfType( + () -> accountService.getAccount(1L), GeneralException.class); + + assertThat(exception.getErrorStatus()).isEqualTo(ErrorStatus.USER_NOT_FOUND); + } + + @Test + void 계정_정보를_조회한다() { + User user = user(); + NotificationSetting setting = NotificationSetting.builder().user(user).sendSlot("07:30").build(); + ReflectionTestUtils.setField(setting, "emailVerified", true); + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + when(notificationSettingRepository.findByUser(user)).thenReturn(Optional.of(setting)); + + AccountResponse response = accountService.getAccount(1L); + + assertThat(response.socialType()).isEqualTo(SocialType.KAKAO); + assertThat(response.receivingEmail()).isEqualTo("a@a.com"); + assertThat(response.emailVerified()).isTrue(); + } + + @Test + void 알림_설정이_없으면_이메일_미확인_상태로_반환한다() { + User user = user(); + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + when(notificationSettingRepository.findByUser(user)).thenReturn(Optional.empty()); + + AccountResponse response = accountService.getAccount(1L); + + assertThat(response.emailVerified()).isFalse(); + } +} From 3d3d6fbd9dface85ccf7f4214f7dc03b58aa7c2a Mon Sep 17 00:00:00 2001 From: yukyoungs Date: Mon, 27 Jul 2026 02:25:43 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[Test]=20#39=20joinedAt=20=EB=A7=A4?= =?UTF-8?q?=ED=95=91=20=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../job_is_be/domain/user/service/AccountServiceTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/com/leets7th/job_is_be/domain/user/service/AccountServiceTest.java b/src/test/java/com/leets7th/job_is_be/domain/user/service/AccountServiceTest.java index 48c7df6..7150e42 100644 --- a/src/test/java/com/leets7th/job_is_be/domain/user/service/AccountServiceTest.java +++ b/src/test/java/com/leets7th/job_is_be/domain/user/service/AccountServiceTest.java @@ -15,6 +15,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; +import java.time.LocalDateTime; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -51,6 +52,8 @@ private User user() { @Test void 계정_정보를_조회한다() { User user = user(); + LocalDateTime createdAt = LocalDateTime.of(2026, 1, 15, 10, 30); + ReflectionTestUtils.setField(user, "createdAt", createdAt); NotificationSetting setting = NotificationSetting.builder().user(user).sendSlot("07:30").build(); ReflectionTestUtils.setField(setting, "emailVerified", true); when(userRepository.findById(1L)).thenReturn(Optional.of(user)); @@ -59,6 +62,7 @@ private User user() { AccountResponse response = accountService.getAccount(1L); assertThat(response.socialType()).isEqualTo(SocialType.KAKAO); + assertThat(response.joinedAt()).isEqualTo(createdAt); assertThat(response.receivingEmail()).isEqualTo("a@a.com"); assertThat(response.emailVerified()).isTrue(); }