From bb67164979bded2d6628bb18580f55ca43c5170e Mon Sep 17 00:00:00 2001 From: user Date: Sat, 11 Jul 2026 05:07:28 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=95=8C=EB=A6=BC=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=9C=A0=EC=A0=80=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=A1=B0=ED=9A=8C=20=EB=B0=8F=20=ED=86=A0?= =?UTF-8?q?=EA=B8=80=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 19 ++++++++++++ .../dto/request/UserNotificationRequest.java | 8 +++++ .../user/dto/response/UserResponse.java | 12 +++++++ .../hackathon/domain/user/entity/User.java | 4 +++ .../domain/user/service/UserService.java | 15 +++++++++ .../domain/user/service/UserServiceTest.java | 31 +++++++++++++++++++ 6 files changed, 89 insertions(+) create mode 100644 src/main/java/com/example/hackathon/domain/user/dto/request/UserNotificationRequest.java create mode 100644 src/main/java/com/example/hackathon/domain/user/dto/response/UserResponse.java 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(); + } }