Skip to content

Commit fb24138

Browse files
authored
Merge pull request #42 from prgrms-web-devcourse-final-project/node/5
[CHORE]: initdata 수정
2 parents ee2263e + 8864e8e commit fb24138

File tree

11 files changed

+253
-46
lines changed

11 files changed

+253
-46
lines changed

back/src/main/java/com/back/domain/comment/service/CommentService.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.back.domain.comment.dto.CommentRequest;
44
import com.back.domain.comment.dto.CommentResponse;
55
import com.back.domain.comment.entity.Comment;
6-
import com.back.domain.comment.enums.CommentSortType;
76
import com.back.domain.comment.mapper.CommentMappers;
87
import com.back.domain.comment.repository.CommentRepository;
98
import com.back.domain.post.entity.Post;
@@ -12,12 +11,9 @@
1211
import com.back.domain.user.repository.UserRepository;
1312
import com.back.global.exception.ApiException;
1413
import com.back.global.exception.ErrorCode;
15-
import jakarta.validation.Valid;
1614
import lombok.RequiredArgsConstructor;
1715
import org.springframework.data.domain.Page;
18-
import org.springframework.data.domain.PageRequest;
1916
import org.springframework.data.domain.Pageable;
20-
import org.springframework.data.domain.Sort;
2117
import org.springframework.stereotype.Service;
2218
import org.springframework.transaction.annotation.Transactional;
2319

@@ -60,6 +56,7 @@ public Long updateComment(Long userId, Long commentId, CommentRequest request) {
6056
return comment.getId();
6157
}
6258

59+
@Transactional
6360
public void deleteComment(Long userId, Long commentId) {
6461
Comment comment = commentRepository.findById(commentId)
6562
.orElseThrow(() -> new ApiException(ErrorCode.COMMENT_NOT_FOUND));

back/src/main/java/com/back/domain/node/controller/BaseLineController.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ public ResponseEntity<BaseNodeDto> getBaseNode(@PathVariable Long baseNodeId) {
5252
// 사용자 전체 트리 조회 (베이스/결정 노드 일괄 반환)
5353
@GetMapping("/{baseLineId}/tree")
5454
public ResponseEntity<TreeDto> getTreeForBaseLine(@PathVariable Long baseLineId) {
55-
// 트리 조회 서비스 호출
5655
TreeDto tree = nodeService.getTreeForBaseLine(baseLineId);
5756
return ResponseEntity.ok(tree);
5857
}

back/src/main/java/com/back/domain/node/repository/BaseLineRepository.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
@Repository
1414
public interface BaseLineRepository extends JpaRepository<BaseLine, Long> {
1515
Optional<BaseLine> findByUser(User user);
16-
long countByUser(User user); // 기본 인덱스 계산용
16+
long countByUser(User user);
17+
// Guest 베이스라인 1개 제한 확인용
18+
boolean existsByUser_id(Long userId);
1719

18-
boolean existsByUserAndTitle(User user, String title); // 충돌 회피용
20+
boolean existsByUserAndTitle(User user, String title);
1921
}

back/src/main/java/com/back/domain/node/service/BaseLineService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.back.domain.node.mapper.NodeMappers;
1414
import com.back.domain.node.repository.BaseLineRepository;
1515
import com.back.domain.node.repository.BaseNodeRepository;
16+
import com.back.domain.user.entity.Role;
1617
import com.back.domain.user.entity.User;
1718
import com.back.domain.user.repository.UserRepository;
1819
import com.back.global.exception.ApiException;
@@ -35,9 +36,15 @@ class BaseLineService {
3536

3637
// 노드 일괄 생성(save chain)
3738
public BaseLineBulkCreateResponse createBaseLineWithNodes(BaseLineBulkCreateRequest request) {
39+
3840
support.validateBulkRequest(request);
3941
User user = userRepository.findById(request.userId())
4042
.orElseThrow(() -> new ApiException(ErrorCode.USER_NOT_FOUND, "User not found: " + request.userId()));
43+
44+
// Guest는 베이스라인 1개 제한
45+
if (user.getRole() == Role.GUEST && baseLineRepository.existsByUser_id(user.getId())) {
46+
throw new ApiException(ErrorCode.GUEST_BASELINE_LIMIT, "Guest user can have only one baseline.");
47+
}
4148
String title = support.normalizeOrAutoTitle(request.title(), user);
4249

4350
BaseLine baseLine = baseLineRepository.save(BaseLine.builder().user(user).title(title).build());

back/src/main/java/com/back/global/exception/ErrorCode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public enum ErrorCode {
4444
NODE_NOT_FOUND(HttpStatus.NOT_FOUND, "N001", "Node Not Found"),
4545
BASE_LINE_NOT_FOUND(HttpStatus.NOT_FOUND, "N002", "BaseLine Not Found"),
4646
DECISION_LINE_NOT_FOUND(HttpStatus.NOT_FOUND, "N003", "DecisionLine Not Found"),
47+
GUEST_BASELINE_LIMIT(HttpStatus.BAD_REQUEST, "N004" , "Guest Base Line Limit Exceeded"),
4748

4849
// Scenario Errors
4950
SCENARIO_NOT_FOUND(HttpStatus.NOT_FOUND, "SC001", "Scenario Not Found"),
Lines changed: 129 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,39 @@
11
package com.back.global.initdata;
22

3-
import com.back.domain.user.entity.Gender;
4-
import com.back.domain.user.entity.Mbti;
5-
import com.back.domain.user.entity.Role;
6-
import com.back.domain.user.entity.User;
3+
import com.back.domain.node.dto.PivotListDto;
4+
import com.back.domain.node.dto.base.BaseLineBulkCreateRequest;
5+
import com.back.domain.node.dto.base.BaseLineBulkCreateResponse;
6+
import com.back.domain.node.dto.decision.DecNodeDto;
7+
import com.back.domain.node.dto.decision.DecisionNodeFromBaseRequest;
8+
import com.back.domain.node.dto.decision.DecisionNodeNextRequest;
9+
import com.back.domain.node.entity.NodeCategory;
10+
import com.back.domain.node.service.NodeService;
11+
import com.back.domain.user.entity.*;
712
import com.back.domain.user.repository.UserRepository;
813
import lombok.RequiredArgsConstructor;
914
import org.springframework.boot.CommandLineRunner;
1015
import org.springframework.security.crypto.password.PasswordEncoder;
1116
import org.springframework.stereotype.Component;
1217

1318
import java.time.LocalDateTime;
19+
import java.util.List;
1420

1521
/**
16-
* 애플리케이션 시작 시 초기 데이터를 생성하는 컴포넌트.
17-
* 개발 환경에서 필요한 기본 사용자(관리자, 일반 사용자)를 데이터베이스에 저장합니다.
22+
* [요약] 기동 시 admin·user1 생성 → user1에 베이스라인(총7: 헤더+피벗5+테일) 1개와 결정라인(총5 노드) 1개 시드 주입.
1823
*/
1924
@Component
2025
@RequiredArgsConstructor
2126
public class InitData implements CommandLineRunner {
2227

2328
private final UserRepository userRepository;
2429
private final PasswordEncoder passwordEncoder;
30+
private final NodeService nodeService;
2531

32+
// user1을 만들고 베이스라인(7)과 결정라인(5)을 시드로 주입한다
2633
@Override
27-
public void run(String... args) throws Exception {
28-
// 애플리케이션 시작 시 초기 사용자 데이터 생성
34+
public void run(String... args) {
2935
if (userRepository.findByEmail("[email protected]").isEmpty()) {
30-
User admin = User.builder()
36+
var admin = User.builder()
3137
3238
.password(passwordEncoder.encode("admin1234!"))
3339
.role(Role.ADMIN)
@@ -41,19 +47,118 @@ public void run(String... args) throws Exception {
4147
userRepository.save(admin);
4248
}
4349

44-
if (userRepository.findByEmail("[email protected]").isEmpty()) {
45-
User user1 = User.builder()
46-
47-
.password(passwordEncoder.encode("user1234!"))
48-
.role(Role.USER)
49-
.username("사용자1")
50-
.nickname("사용자닉네임")
51-
.birthdayAt(LocalDateTime.of(1995, 5, 10, 0, 0))
52-
.gender(Gender.F)
53-
.mbti(Mbti.ENFP)
54-
.beliefs("개인주의")
55-
.build();
56-
userRepository.save(user1);
57-
}
50+
var user1 = userRepository.findByEmail("[email protected]")
51+
.orElseGet(() -> userRepository.save(
52+
User.builder()
53+
54+
.password(passwordEncoder.encode("user1234!"))
55+
.role(Role.USER)
56+
.username("사용자1")
57+
.nickname("사용자닉네임")
58+
.birthdayAt(LocalDateTime.of(1995, 5, 10, 0, 0))
59+
.gender(Gender.F)
60+
.mbti(Mbti.ENFP)
61+
.beliefs("개인주의")
62+
.build()
63+
));
64+
65+
BaseLineBulkCreateResponse baseRes = nodeService.createBaseLineWithNodes(
66+
new BaseLineBulkCreateRequest(
67+
user1.getId(),
68+
"user1-기본 라인",
69+
List.of(
70+
new BaseLineBulkCreateRequest.BaseNodePayload(
71+
NodeCategory.EDUCATION, "중학교 진학", "일반계 선택", 18, "중등 입학 및 진로 탐색 시작"
72+
),
73+
new BaseLineBulkCreateRequest.BaseNodePayload(
74+
NodeCategory.EDUCATION, "고교 진학", "이과 트랙", 20, "수학·물리 집중 선택"
75+
),
76+
new BaseLineBulkCreateRequest.BaseNodePayload(
77+
NodeCategory.EDUCATION, "대학 합격", "컴공 전공", 22, "알고리즘/네트워크 관심"
78+
),
79+
new BaseLineBulkCreateRequest.BaseNodePayload(
80+
NodeCategory.CAREER, "인턴 경험", "백엔드 인턴", 24, "스프링 부트 실무 체험"
81+
),
82+
new BaseLineBulkCreateRequest.BaseNodePayload(
83+
NodeCategory.CAREER, "첫 직장", "주니어 백엔드", 26, "API/DB 설계 중심"
84+
)
85+
)
86+
)
87+
);
88+
89+
Long baseLineId = baseRes.baseLineId();
90+
PivotListDto pivots = nodeService.getPivotBaseNodes(baseLineId);
91+
if (pivots.pivots() == null || pivots.pivots().isEmpty()) return;
92+
93+
DecNodeDto d0 = nodeService.createDecisionNodeFromBase(
94+
new DecisionNodeFromBaseRequest(
95+
user1.getId(),
96+
baseLineId,
97+
0,
98+
null,
99+
0,
100+
NodeCategory.CAREER,
101+
"개발자 커리어 진입",
102+
List.of("자바/스프링", "파이썬/데이터"),
103+
0,
104+
"백엔드 중심 트랙을 초기 선택지로 제시"
105+
)
106+
);
107+
108+
DecNodeDto d1 = nodeService.createDecisionNodeNext(
109+
new DecisionNodeNextRequest(
110+
user1.getId(),
111+
d0.id(),
112+
NodeCategory.CAREER,
113+
"클라우드 기초",
114+
null,
115+
List.of("AWS 기초", "GCP 기초"),
116+
0,
117+
0,
118+
"EC2/RDS·CI/CD 파이프라인 구축"
119+
)
120+
);
121+
122+
DecNodeDto d2 = nodeService.createDecisionNodeNext(
123+
new DecisionNodeNextRequest(
124+
user1.getId(),
125+
d1.id(),
126+
NodeCategory.CAREER,
127+
"보안 기초",
128+
null,
129+
List.of("웹 보안", "네트워크 보안"),
130+
0,
131+
0,
132+
"JWT·세션·CSRF/XSS 대응 심화"
133+
)
134+
);
135+
136+
DecNodeDto d3 = nodeService.createDecisionNodeNext(
137+
new DecisionNodeNextRequest(
138+
user1.getId(),
139+
d2.id(),
140+
NodeCategory.CAREER,
141+
"대용량 처리",
142+
null,
143+
List.of("캐시·큐", "검색"),
144+
0,
145+
0,
146+
"Redis·Kafka·Elasticsearch 실습"
147+
)
148+
);
149+
150+
nodeService.createDecisionNodeNext(
151+
new DecisionNodeNextRequest(
152+
user1.getId(),
153+
d3.id(),
154+
NodeCategory.CAREER,
155+
"운영/관측성",
156+
null,
157+
List.of("로그·모니터링", "SLO/알림"),
158+
0,
159+
0,
160+
"프로덕션 운영 지표와 알림 체계 정착"
161+
)
162+
);
58163
}
59-
}
164+
}

back/src/test/java/com/back/domain/comment/controller/CommentControllerTest.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.back.domain.user.repository.UserRepository;
1313
import com.back.global.security.CustomUserDetails;
1414
import com.fasterxml.jackson.databind.ObjectMapper;
15+
import jakarta.persistence.EntityManager;
1516
import org.junit.jupiter.api.BeforeEach;
1617
import org.junit.jupiter.api.DisplayName;
1718
import org.junit.jupiter.api.Nested;
@@ -23,8 +24,9 @@
2324
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
2425
import org.springframework.security.core.context.SecurityContextHolder;
2526
import org.springframework.test.context.ActiveProfiles;
27+
import org.springframework.test.context.jdbc.Sql;
28+
import org.springframework.test.context.jdbc.SqlConfig;
2629
import org.springframework.test.web.servlet.MockMvc;
27-
import org.springframework.transaction.annotation.Transactional;
2830
import org.springframework.util.ReflectionUtils;
2931

3032
import java.lang.reflect.Field;
@@ -40,20 +42,36 @@
4042
@ActiveProfiles("test")
4143
@SpringBootTest
4244
@AutoConfigureMockMvc(addFilters = false)
43-
@Transactional
45+
@SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)
46+
@Sql(
47+
statements = {
48+
"SET REFERENTIAL_INTEGRITY FALSE",
49+
"TRUNCATE TABLE COMMENTS",
50+
"TRUNCATE TABLE POST",
51+
"TRUNCATE TABLE USERS",
52+
53+
"ALTER TABLE COMMENTS ALTER COLUMN id RESTART WITH 1",
54+
"ALTER TABLE POST ALTER COLUMN id RESTART WITH 1",
55+
"ALTER TABLE USERS ALTER COLUMN id RESTART WITH 1",
56+
"SET REFERENTIAL_INTEGRITY TRUE"
57+
},
58+
executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD
59+
)
4460
class CommentControllerTest {
4561

4662
@Autowired private UserRepository userRepository;
4763
@Autowired private PostRepository postRepository;
4864
@Autowired private CommentRepository commentRepository;
4965
@Autowired private MockMvc mockMvc;
5066
@Autowired private ObjectMapper objectMapper;
67+
@Autowired private EntityManager em;
5168

5269
private User testUser;
5370
private User anotherUser;
5471
private Post testPost;
5572
private Comment testComment;
5673

74+
5775
@BeforeEach
5876
void setUp() {
5977
String uid1 = UUID.randomUUID().toString().substring(0, 5);

back/src/test/java/com/back/domain/node/controller/BaseLineControllerTest.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
2121
import org.springframework.boot.test.context.SpringBootTest;
2222
import org.springframework.http.MediaType;
23+
import org.springframework.test.context.jdbc.Sql;
24+
import org.springframework.test.context.jdbc.SqlConfig;
2325
import org.springframework.test.web.servlet.MockMvc;
2426

2527
import java.time.LocalDateTime;
@@ -35,6 +37,25 @@
3537
@AutoConfigureMockMvc(addFilters = false)
3638
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
3739
@DisplayName("Re:Life — BaseLine/BaseNode 통합 테스트")
40+
@SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)
41+
@Sql(
42+
statements = {
43+
"SET REFERENTIAL_INTEGRITY FALSE",
44+
"TRUNCATE TABLE DECISION_NODES",
45+
"TRUNCATE TABLE DECISION_LINES",
46+
"TRUNCATE TABLE BASE_NODES",
47+
"TRUNCATE TABLE BASE_LINES",
48+
"TRUNCATE TABLE USERS",
49+
50+
"ALTER TABLE DECISION_NODES ALTER COLUMN ID RESTART WITH 1",
51+
"ALTER TABLE DECISION_LINES ALTER COLUMN ID RESTART WITH 1",
52+
"ALTER TABLE BASE_NODES ALTER COLUMN ID RESTART WITH 1",
53+
"ALTER TABLE BASE_LINES ALTER COLUMN ID RESTART WITH 1",
54+
"ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 1",
55+
"SET REFERENTIAL_INTEGRITY TRUE"
56+
},
57+
executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD
58+
)
3859
public class BaseLineControllerTest {
3960

4061
@Autowired private MockMvc mockMvc;
@@ -46,17 +67,17 @@ public class BaseLineControllerTest {
4667

4768
private Long userId;
4869

49-
@BeforeAll
70+
@BeforeEach
5071
void initUser() {
5172
String uid = UUID.randomUUID().toString().substring(0, 8);
5273
User user = User.builder()
5374
.email("user_" + uid + "@test.local")
54-
.role(Role.GUEST)
75+
.role(Role.USER)
5576
.birthdayAt(LocalDateTime.now().minusYears(25))
5677
.gender(Gender.M)
5778
.mbti(Mbti.INTJ)
5879
.beliefs("NONE")
59-
.authProvider(AuthProvider.GUEST)
80+
.authProvider(AuthProvider.LOCAL)
6081
.nickname("tester-" + uid)
6182
.username("name-" + uid)
6283
.build();

0 commit comments

Comments
 (0)