diff --git a/src/main/java/com/example/hackathon/domain/user/controller/UserController.java b/src/main/java/com/example/hackathon/domain/user/controller/UserController.java index bb03fd1..30914b1 100644 --- a/src/main/java/com/example/hackathon/domain/user/controller/UserController.java +++ b/src/main/java/com/example/hackathon/domain/user/controller/UserController.java @@ -4,8 +4,10 @@ import com.example.hackathon.domain.user.dto.request.UserCreateRequest; import com.example.hackathon.domain.user.dto.request.ActiveTeamRequest; import com.example.hackathon.domain.user.dto.request.UserEmailRequest; +import com.example.hackathon.domain.user.dto.request.UserNotificationRequest; import com.example.hackathon.domain.user.dto.response.UserCreateResponse; import com.example.hackathon.domain.user.dto.response.UserHomeResponse; +import com.example.hackathon.domain.user.dto.response.UserResponse; import com.example.hackathon.domain.user.service.UserService; import com.example.hackathon.global.response.ApiResponse; @@ -82,4 +84,21 @@ public ResponseEntity> getHomeData( UserHomeResponse response = userService.getHomeData(userId); return ResponseEntity.ok(ApiResponse.ok("홈 화면 데이터 조회 성공", response)); } + + // 8. 유저 정보 조회 (GET -> 알림 설정 화면 진입 시 이용) + @GetMapping("/{userId}") + public ResponseEntity> getUser(@PathVariable Long userId) { + UserResponse response = userService.getUser(userId); + return ResponseEntity.ok(ApiResponse.ok("유저 정보 조회 성공", response)); + } + + // 9. 알림 허용 여부 토글 (PATCH) + @PatchMapping("/{userId}/notification") + public ResponseEntity> updateNotificationSetting( + @PathVariable Long userId, + @Valid @RequestBody UserNotificationRequest request + ) { + userService.updateNotificationSetting(userId, request.enabled()); + return ResponseEntity.ok(ApiResponse.ok("알림 설정이 수정되었습니다.", "Success")); + } } \ No newline at end of file diff --git a/src/main/java/com/example/hackathon/domain/user/dto/request/UserNotificationRequest.java b/src/main/java/com/example/hackathon/domain/user/dto/request/UserNotificationRequest.java new file mode 100644 index 0000000..12fa576 --- /dev/null +++ b/src/main/java/com/example/hackathon/domain/user/dto/request/UserNotificationRequest.java @@ -0,0 +1,8 @@ +package com.example.hackathon.domain.user.dto.request; + +import jakarta.validation.constraints.NotNull; + +public record UserNotificationRequest( + @NotNull(message = "알림 설정값은 필수입니다.") + Boolean enabled +) {} diff --git a/src/main/java/com/example/hackathon/domain/user/dto/response/UserResponse.java b/src/main/java/com/example/hackathon/domain/user/dto/response/UserResponse.java new file mode 100644 index 0000000..9f371c6 --- /dev/null +++ b/src/main/java/com/example/hackathon/domain/user/dto/response/UserResponse.java @@ -0,0 +1,12 @@ +package com.example.hackathon.domain.user.dto.response; + +public record UserResponse( + Long id, + String nickname, + String email, + boolean emailNotificationEnabled +) { + public static UserResponse of(Long id, String nickname, String email, boolean emailNotificationEnabled) { + return new UserResponse(id, nickname, email, emailNotificationEnabled); + } +} diff --git a/src/main/java/com/example/hackathon/domain/user/entity/User.java b/src/main/java/com/example/hackathon/domain/user/entity/User.java index 007f0a3..ef5e8b7 100644 --- a/src/main/java/com/example/hackathon/domain/user/entity/User.java +++ b/src/main/java/com/example/hackathon/domain/user/entity/User.java @@ -127,4 +127,8 @@ public void updateLastPopupShownDate(LocalDate date) { public void updateLastSettlementDate(LocalDate date) { this.lastSettlementDate = date; } + + public void updateEmailNotificationEnabled(boolean enabled) { + this.emailNotificationEnabled = enabled; + } } \ No newline at end of file diff --git a/src/main/java/com/example/hackathon/domain/user/service/UserService.java b/src/main/java/com/example/hackathon/domain/user/service/UserService.java index 8dec6bd..7752e30 100644 --- a/src/main/java/com/example/hackathon/domain/user/service/UserService.java +++ b/src/main/java/com/example/hackathon/domain/user/service/UserService.java @@ -4,6 +4,7 @@ import com.example.hackathon.domain.user.repository.UserRepository; import com.example.hackathon.domain.user.dto.response.UserCreateResponse; import com.example.hackathon.domain.user.dto.response.UserHomeResponse; +import com.example.hackathon.domain.user.dto.response.UserResponse; import com.example.hackathon.domain.user.dto.response.UserHomeResponse.HomeMemberStatus; import com.example.hackathon.domain.user.dto.response.UserHomeResponse.HomePopupInfo; import com.example.hackathon.domain.user.entity.DailySettlementLog; @@ -102,6 +103,20 @@ public void updateUserEmail(Long userId, String email) { user.updateEmail(email); } + @Transactional(readOnly = true) + public UserResponse getUser(Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new BusinessException(ErrorCode.USER_ERROR_404_NOT_FOUND)); + return UserResponse.of(user.getId(), user.getNickname(), user.getEmail(), user.isEmailNotificationEnabled()); + } + + @Transactional + public void updateNotificationSetting(Long userId, boolean enabled) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new BusinessException(ErrorCode.USER_ERROR_404_NOT_FOUND)); + user.updateEmailNotificationEnabled(enabled); + } + @Transactional public UserHomeResponse getHomeData(Long userId) { User user = userRepository.findByIdForUpdate(userId) diff --git a/src/test/java/com/example/hackathon/domain/user/service/UserServiceTest.java b/src/test/java/com/example/hackathon/domain/user/service/UserServiceTest.java index 604d02d..f3ff88a 100644 --- a/src/test/java/com/example/hackathon/domain/user/service/UserServiceTest.java +++ b/src/test/java/com/example/hackathon/domain/user/service/UserServiceTest.java @@ -13,6 +13,7 @@ import com.example.hackathon.domain.team.repository.TeamMemberRepository; import com.example.hackathon.domain.team.repository.TeamRepository; import com.example.hackathon.domain.user.dto.response.UserHomeResponse; +import com.example.hackathon.domain.user.dto.response.UserResponse; import com.example.hackathon.domain.user.entity.DailySettlementLog; import com.example.hackathon.domain.user.entity.User; import com.example.hackathon.domain.user.repository.DailySettlementLogRepository; @@ -171,4 +172,34 @@ void homeDataThrowsWhenDetoxTimeNull() { () -> userService.getHomeData(user.getId()) ); } + + @Test + @DisplayName("유저 상세 조회 시 등록 정보가 정상 반환된다") + void getUserDetailsSuccess() { + // given + User user = createUser("길동", "test@test.com"); + + // when + UserResponse response = userService.getUser(user.getId()); + + // then + assertThat(response.id()).isEqualTo(user.getId()); + assertThat(response.nickname()).isEqualTo("길동"); + assertThat(response.email()).isEqualTo("test@test.com"); + assertThat(response.emailNotificationEnabled()).isTrue(); + } + + @Test + @DisplayName("알림 토글 API 호출 시 수신동의 플래그가 정상 업데이트된다") + void updateNotificationSettingSuccess() { + // given + User user = createUser("길동", "test@test.com"); + + // when + userService.updateNotificationSetting(user.getId(), false); + + // then + User updated = userRepository.findById(user.getId()).orElseThrow(); + assertThat(updated.isEmailNotificationEnabled()).isFalse(); + } }