Skip to content

Commit 653773b

Browse files
authored
Merge pull request #138 from Money-Touch/feat/#57
✨feat: 회원 삭제 api 추가
2 parents 9f1837e + 07cbd53 commit 653773b

7 files changed

Lines changed: 101 additions & 22 deletions

File tree

src/main/java/com/server/money_touch/domain/consumptionRecord/entity/ConsumptionCategory.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package com.server.money_touch.domain.consumptionRecord.entity;
22

3+
import com.server.money_touch.domain.budget.entity.BudgetCategory;
34
import com.server.money_touch.domain.budget.enums.CategoryType;
45
import com.server.money_touch.domain.user.entity.User;
56
import com.server.money_touch.global.apiPayload.code.BaseEntity;
67
import jakarta.persistence.*;
78
import lombok.*;
89

10+
import java.util.ArrayList;
11+
import java.util.List;
12+
913
@Table(name = "consumption_category", uniqueConstraints = {
1014
@UniqueConstraint(columnNames = {"user_id", "budgetCategoryName"})
1115
})
@@ -29,6 +33,9 @@ public class ConsumptionCategory extends BaseEntity {
2933
@JoinColumn(name = "user_id", nullable = false)
3034
private User user;
3135

36+
@OneToMany(mappedBy = "consumptionCategory", cascade = CascadeType.ALL, orphanRemoval = true)
37+
private List<BudgetCategory> budgetCategories = new ArrayList<>();
38+
3239
public void updateCategoryType(CategoryType newType) {
3340
this.budgetCategoryType = newType;
3441
}

src/main/java/com/server/money_touch/domain/user/controller/UserController.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.server.money_touch.domain.badge.service.BadgeCommandService;
44
import com.server.money_touch.domain.user.dto.UserRequest;
55
import com.server.money_touch.domain.user.dto.UserResponse;
6+
import com.server.money_touch.domain.user.entity.User;
67
import com.server.money_touch.domain.user.service.user.UserCommandService;
78
import com.server.money_touch.domain.user.service.user.UserQueryService;
89
import com.server.money_touch.global.apiPayload.ApiResponse;
@@ -111,6 +112,17 @@ public ApiResponse<String> validateNickname(@RequestParam("nickname") String nic
111112
}
112113
}
113114

115+
@Operation(summary = "유저 삭제 API", description = "회원 ID를 통해 회원을 삭제하는 api입니다.")
116+
@ApiErrorCodeExamples({
117+
@ApiErrorCodeExample(value = ErrorStatus.class, name = "USER_NOT_FOUND"),
118+
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_BAD_REQUEST"),
119+
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_INTERNAL_SERVER_ERROR")
120+
})
121+
@PostMapping("/delete")
122+
public ApiResponse<UserResponse.UserDeleteResultDTO> DeleteUser(@RequestParam Long userId) {
123+
return ApiResponse.onSuccess(userCommandService.deleteUser(userId));
124+
}
125+
114126
@Operation(
115127
summary = "로컬 회원가입 API",
116128
description = "이메일과 비밀번호를 사용한 로컬 회원가입 방식의 API입니다." + "이용약관 동의 리스트를 한꺼번에 보내주셔야합니다!"

src/main/java/com/server/money_touch/domain/user/dto/UserResponse.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ public static class UserDetailCreateResultDTO{
3939
private Long userDetailId;
4040
}
4141

42+
@Builder
43+
@Getter
44+
@NoArgsConstructor
45+
@AllArgsConstructor
46+
@Schema(description = "유저 상세 정보 등록 응답 정보")
47+
public static class UserDeleteResultDTO{
48+
49+
@Schema(description = "유저 상세 정보 ID", example = "1")
50+
private Long userId;
51+
private String message;
52+
}
53+
4254
@Builder
4355
@Getter
4456
@NoArgsConstructor

src/main/java/com/server/money_touch/domain/user/entity/User.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
package com.server.money_touch.domain.user.entity;
22

33

4+
import com.server.money_touch.domain.badge.entity.Badge;
5+
import com.server.money_touch.domain.badge.entity.UserBadge;
6+
import com.server.money_touch.domain.budget.entity.Budget;
7+
import com.server.money_touch.domain.budget.entity.BudgetCategory;
8+
import com.server.money_touch.domain.consumptionMbti.entity.ConsumptionMbti;
9+
import com.server.money_touch.domain.consumptionRecord.entity.*;
10+
import com.server.money_touch.domain.fixedConsumption.entity.FixedConsumption;
11+
import com.server.money_touch.domain.notification.entity.Notification;
12+
import com.server.money_touch.domain.routine.entity.Routine;
413
import com.server.money_touch.domain.user.enums.AuthType;
514
import com.server.money_touch.domain.user.enums.Role;
615
import com.server.money_touch.global.apiPayload.code.BaseEntity;
716
import jakarta.persistence.*;
817
import lombok.*;
918

19+
import java.util.ArrayList;
20+
import java.util.List;
21+
1022
@Builder
1123
@Getter
1224
@Setter
@@ -49,5 +61,39 @@ public class User extends BaseEntity {
4961
@JoinColumn(name = "user_detail_id")
5062
private UserDetail userDetail;
5163

64+
// 회원 삭제를 위한 Cascade 설정
65+
66+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
67+
private List<ConsumptionCategory> categories = new ArrayList<>();
68+
69+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
70+
private List<TotalConsumption> totalConsumption;
71+
72+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
73+
private List<Budget> budgets = new ArrayList<>();
74+
75+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
76+
private List<Reaction> reactions = new ArrayList<>();
77+
78+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
79+
private List<ConsumptionRecord> consumptionRecords = new ArrayList<>();
80+
81+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
82+
private List<Comment> comments = new ArrayList<>();
83+
84+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
85+
private List<Notification> notifications = new ArrayList<>();
86+
87+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
88+
private List<UserBadge> badges = new ArrayList<>();
89+
90+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
91+
private List<FixedConsumption> fixedConsumptionList = new ArrayList<>();
92+
93+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
94+
private List<Routine> routines = new ArrayList<>();
95+
96+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
97+
private List<ConsumptionMbti> consumptionMbtiList = new ArrayList<>();
5298

5399
}

src/main/java/com/server/money_touch/domain/user/service/user/UserCommandService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public interface UserCommandService {
1313
UserResponse.LoginResultDTO refreshToken(String refreshToken);
1414
// 유저 상세정보 등록
1515
UserResponse.UserDetailCreateResultDTO saveUserDetails(Long userId, UserRequest.UserDetailCreateDTO request);
16+
// 회원 삭제
17+
UserResponse.UserDeleteResultDTO deleteUser(Long userId);
18+
1619

1720

1821
}

src/main/java/com/server/money_touch/domain/user/service/user/UserCommandServiceImpl.java

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ public class UserCommandServiceImpl implements UserCommandService {
4949
private final UserDetailRepository userDetailRepository;
5050
private final PasswordEncoder passwordEncoder;
5151
private final TokenProvider tokenProvider;
52-
private final UserQueryService userQueryService;
5352
private final BudgetCommandService budgetCommandService;
5453
private final TotalConsumptionRepository totalConsumptionRepository;
5554

@@ -78,17 +77,12 @@ public UserResponse.UserDetailCreateResultDTO saveUserDetails(Long userId, UserR
7877
return UserConverter.toUserDetailCreateResultDTO(userDetail.getId());
7978
}
8079

81-
/**
82-
* 로컬 회원가입
83-
*/
80+
// 로컬 회원가입
8481
@Override
8582
@Transactional
8683
public UserResponse.UserCreateResultDTO signUpLocal(UserRequest.LocalSignUpDTO request) {
8784
log.info("로컬 회원가입 시작 - email: {}", request.getEmail());
8885

89-
// 이메일 중복 검증
90-
// validateDuplicateEmail(request.getEmail()); TODO: 이메일 인증요청시 중복검사 하기
91-
9286
// 비밀번호 암호화
9387
String encodedPassword = passwordEncoder.encode(request.getPassword());
9488

@@ -132,9 +126,7 @@ public UserResponse.UserCreateResultDTO signUpLocal(UserRequest.LocalSignUpDTO r
132126
.build();
133127
}
134128

135-
/**
136-
* 로컬 로그인
137-
*/
129+
// 로컬 로그인
138130
@Override
139131
@Transactional
140132
public UserResponse.LoginResultDTO loginLocal(UserRequest.LocalLoginDTO request) {
@@ -168,9 +160,7 @@ public UserResponse.LoginResultDTO loginLocal(UserRequest.LocalLoginDTO request)
168160
.build();
169161
}
170162

171-
/**
172-
* 토큰 갱신
173-
*/
163+
// 로컬 갱신
174164
@Override
175165
@Transactional
176166
public UserResponse.LoginResultDTO refreshToken(String refreshToken) {
@@ -191,9 +181,21 @@ public UserResponse.LoginResultDTO refreshToken(String refreshToken) {
191181
.build();
192182
}
193183

194-
/**
195-
* Authentication 객체 생성
196-
*/
184+
// 회원 삭제
185+
@Transactional
186+
@Override
187+
public UserResponse.UserDeleteResultDTO deleteUser(Long userId) {
188+
// 1. 회원 조회
189+
User user = userRepository.findById(userId).orElseThrow(() -> new ErrorHandler(ErrorStatus.USER_NOT_FOUND));
190+
191+
// 2. 삭제
192+
userRepository.delete(user);
193+
194+
// 3. 응답 DTO 생성
195+
return new UserResponse.UserDeleteResultDTO(userId, "회원 삭제 성공");
196+
}
197+
198+
// Authentication 객체 생성
197199
private Authentication createAuthentication(User user) {
198200
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(user.getRole().name());
199201
LocalLogin localLogin = user.getLocalLogin();
@@ -209,9 +211,7 @@ private Authentication createAuthentication(User user) {
209211
);
210212
}
211213

212-
/**
213-
* 약관 동의 처리
214-
*/
214+
// 약관 동의 처리
215215
private void processAgreements(User user, List<UserRequest.AgreementDTO> agreements) {
216216
if (agreements != null && !agreements.isEmpty()) {
217217
log.info("약관 동의 처리 - userId: {}, 동의 항목 수: {}", user.getId(), agreements.size());
@@ -229,9 +229,7 @@ private void processAgreements(User user, List<UserRequest.AgreementDTO> agreeme
229229
}
230230
}
231231

232-
/**
233-
* 필수 약관 여부 확인
234-
*/
232+
// 필수 여부 확인
235233
private boolean isRequiredTerm(Long termsId) {
236234
// 실제로는 Terms 엔티티에서 필수 여부를 확인해야 함
237235
// 예시로 ID 1, 2를 필수 약관으로 가정

src/main/java/com/server/money_touch/domain/user/service/user/UserQueryServiceImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public Boolean existsByNickname(String nickname) {
4343
return userRepository.existsByNickname(nickname);
4444
}
4545

46+
// 이메일 인증번호 발송
4647
public void requestEmailVerification(String toEmail) throws IOException {
4748
// 이메일 중복 체크
4849
if (existsByEmail(toEmail)) {

0 commit comments

Comments
 (0)