Skip to content

Commit e1254ac

Browse files
Merge pull request #280 from prgrms-web-devcourse-final-project/refactor/EA3-200-application
[EA3-200] refactor: 스터디 신청 로직 리팩터링
2 parents c032ecc + 6fd062c commit e1254ac

13 files changed

+94
-79
lines changed

src/main/java/grep/neogulcoder/domain/study/Study.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public class Study extends BaseEntity {
5050
@Version
5151
private Long version;
5252

53+
private static final int MAX_JOINED_STUDY_COUNT = 10;
54+
5355
protected Study() {
5456
}
5557

@@ -122,4 +124,8 @@ public boolean isReviewableAt(LocalDateTime currentDateTime) {
122124
return (currentDateTime.isEqual(this.endDate) || currentDateTime.isAfter(this.endDate)) &&
123125
(currentDateTime.isEqual(reviewableDateTime) || currentDateTime.isBefore(reviewableDateTime));
124126
}
127+
128+
public static boolean isOverJoinLimit(int joinedStudyCount) {
129+
return joinedStudyCount >= MAX_JOINED_STUDY_COUNT;
130+
}
125131
}

src/main/java/grep/neogulcoder/domain/study/service/StudyService.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@
4040
import java.util.List;
4141
import java.util.Optional;
4242

43-
import static grep.neogulcoder.domain.study.enums.StudyMemberRole.LEADER;
43+
import static grep.neogulcoder.domain.study.enums.StudyMemberRole.*;
4444
import static grep.neogulcoder.domain.study.exception.code.StudyErrorCode.*;
45-
import static grep.neogulcoder.domain.users.exception.code.UserErrorCode.USER_NOT_FOUND;
45+
import static grep.neogulcoder.domain.users.exception.code.UserErrorCode.*;
4646

4747
@Transactional(readOnly = true)
4848
@RequiredArgsConstructor
@@ -184,8 +184,8 @@ private StudyMember getStudyMemberById(Long studyId, Long userId) {
184184
}
185185

186186
private void validateStudyCreateLimit(Long userId) {
187-
int count = studyRepository.countByUserIdAndActivatedTrueAndFinishedFalse(userId);
188-
if (count >= 10) {
187+
int joinedStudyCount = studyRepository.countByUserIdAndActivatedTrueAndFinishedFalse(userId);
188+
if (Study.isOverJoinLimit(joinedStudyCount)) {
189189
throw new BusinessException(STUDY_CREATE_LIMIT_EXCEEDED);
190190
}
191191
}

src/main/java/grep/neogulcoder/domain/studyapplication/controller/ApplicationController.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import lombok.RequiredArgsConstructor;
1212
import org.springframework.data.domain.Pageable;
1313
import org.springframework.data.web.PageableDefault;
14+
import org.springframework.http.ResponseEntity;
1415
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1516
import org.springframework.web.bind.annotation.*;
1617

@@ -22,38 +23,38 @@ public class ApplicationController implements ApplicationSpecification {
2223
private final ApplicationService applicationService;
2324

2425
@GetMapping("/{recruitment-post-id}/applications")
25-
public ApiResponse<ReceivedApplicationPagingResponse> getReceivedApplications(@PathVariable("recruitment-post-id") Long recruitmentPostId,
26-
@PageableDefault(size = 5) Pageable pageable,
27-
@AuthenticationPrincipal Principal userDetails) {
28-
return ApiResponse.success(applicationService.getReceivedApplicationsPaging(recruitmentPostId, pageable, userDetails.getUserId()));
26+
public ResponseEntity<ApiResponse<ReceivedApplicationPagingResponse>> getReceivedApplications(@PathVariable("recruitment-post-id") Long recruitmentPostId,
27+
@PageableDefault(size = 5) Pageable pageable,
28+
@AuthenticationPrincipal Principal userDetails) {
29+
return ResponseEntity.ok(ApiResponse.success(applicationService.getReceivedApplicationsPaging(recruitmentPostId, pageable, userDetails.getUserId())));
2930
}
3031

3132
@GetMapping("/applications")
32-
public ApiResponse<MyApplicationPagingResponse> getMyStudyApplications(@PageableDefault(size = 12) Pageable pageable,
33+
public ResponseEntity<ApiResponse<MyApplicationPagingResponse>> getMyStudyApplications(@PageableDefault(size = 12) Pageable pageable,
3334
@RequestParam(required = false) ApplicationStatus status,
3435
@AuthenticationPrincipal Principal userDetails) {
35-
return ApiResponse.success(applicationService.getMyStudyApplicationsPaging(pageable, userDetails.getUserId(), status));
36+
return ResponseEntity.ok(ApiResponse.success(applicationService.getMyStudyApplicationsPaging(pageable, userDetails.getUserId(), status)));
3637
}
3738

3839
@PostMapping("/{recruitment-post-id}/applications")
39-
public ApiResponse<Long> createApplication(@PathVariable("recruitment-post-id") Long recruitmentPostId,
40+
public ResponseEntity<ApiResponse<Long>> createApplication(@PathVariable("recruitment-post-id") Long recruitmentPostId,
4041
@RequestBody @Valid ApplicationCreateRequest request,
4142
@AuthenticationPrincipal Principal userDetails) {
4243
Long id = applicationService.createApplication(recruitmentPostId, request, userDetails.getUserId());
43-
return ApiResponse.success(id);
44+
return ResponseEntity.ok(ApiResponse.success(id));
4445
}
4546

4647
@PostMapping("/applications/{applicationId}/approve")
47-
public ApiResponse<Void> approveApplication(@PathVariable("applicationId") Long applicationId,
48+
public ResponseEntity<ApiResponse<Void>> approveApplication(@PathVariable("applicationId") Long applicationId,
4849
@AuthenticationPrincipal Principal userDetails) {
4950
applicationService.approveApplication(applicationId, userDetails.getUserId());
50-
return ApiResponse.noContent();
51+
return ResponseEntity.ok(ApiResponse.noContent());
5152
}
5253

5354
@PostMapping("/applications/{applicationId}/reject")
54-
public ApiResponse<Void> rejectApplication(@PathVariable("applicationId") Long applicationId,
55+
public ResponseEntity<ApiResponse<Void>> rejectApplication(@PathVariable("applicationId") Long applicationId,
5556
@AuthenticationPrincipal Principal userDetails) {
5657
applicationService.rejectApplication(applicationId, userDetails.getUserId());
57-
return ApiResponse.noContent();
58+
return ResponseEntity.ok(ApiResponse.noContent());
5859
}
5960
}

src/main/java/grep/neogulcoder/domain/studyapplication/controller/ApplicationSpecification.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,23 @@
99
import io.swagger.v3.oas.annotations.Operation;
1010
import io.swagger.v3.oas.annotations.tags.Tag;
1111
import org.springframework.data.domain.Pageable;
12+
import org.springframework.http.ResponseEntity;
1213

1314
@Tag(name = "StudyApplication", description = "스터디 신청 API")
1415
public interface ApplicationSpecification {
1516

1617
@Operation(summary = "모집글 신청 목록 조회", description = "스터디장(모집글 작성자)이 신청 목록을 조회합니다.")
17-
public ApiResponse<ReceivedApplicationPagingResponse> getReceivedApplications(Long recruitmentPostId, Pageable pageable, Principal userDetails);
18+
ResponseEntity<ApiResponse<ReceivedApplicationPagingResponse>> getReceivedApplications(Long recruitmentPostId, Pageable pageable, Principal userDetails);
1819

1920
@Operation(summary = "내 스터디 신청 목록 조회", description = "내가 신청한 스터디의 목록을 조회합니다.")
20-
ApiResponse<MyApplicationPagingResponse> getMyStudyApplications(Pageable pageable, ApplicationStatus status, Principal userDetails);
21+
ResponseEntity<ApiResponse<MyApplicationPagingResponse>> getMyStudyApplications(Pageable pageable, ApplicationStatus status, Principal userDetails);
2122

2223
@Operation(summary = "스터디 신청 생성", description = "스터디를 신청합니다.")
23-
ApiResponse<Long> createApplication(Long recruitmentPostId, ApplicationCreateRequest request, Principal userDetails);
24+
ResponseEntity<ApiResponse<Long>> createApplication(Long recruitmentPostId, ApplicationCreateRequest request, Principal userDetails);
2425

2526
@Operation(summary = "스터디 신청 승인", description = "스터디장이 스터디 신청을 승인합니다.")
26-
ApiResponse<Void> approveApplication(Long applicationId, Principal userDetails);
27+
ResponseEntity<ApiResponse<Void>> approveApplication(Long applicationId, Principal userDetails);
2728

2829
@Operation(summary = "스터디 신청 거절", description = "스터디장이 스터디 신청을 거절합니다.")
29-
ApiResponse<Void> rejectApplication(Long applicationId, Principal userDetails);
30+
ResponseEntity<ApiResponse<Void>> rejectApplication(Long applicationId, Principal userDetails);
3031
}

src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationPagingResponse.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ public class MyApplicationPagingResponse {
2727
"\"status\": \"PENDING\"" +
2828
"}]"
2929
)
30-
private List<MyApplicationResponse> applications;
30+
private final List<MyApplicationResponse> applications;
3131

3232
@Schema(description = "총 페이지 수", example = "2")
33-
private int totalPage;
33+
private final int totalPage;
3434

3535
@Schema(description = "총 요소 개수", example = "10")
36-
private int totalElementCount;
36+
private final int totalElementCount;
3737

3838
@Schema(example = "false", description = "다음 페이지 여부")
39-
private boolean hasNext;
39+
private final boolean hasNext;
4040

4141
@Builder
4242
private MyApplicationPagingResponse(Page<MyApplicationResponse> page) {

src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/MyApplicationResponse.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,40 @@
1313
public class MyApplicationResponse {
1414

1515
@Schema(description = "모집글 번호", example = "1")
16-
private Long recruitmentPostId;
16+
private final Long recruitmentPostId;
1717

1818
@Schema(description = "스터디 이름", example = "자바 스터디")
19-
private String name;
19+
private final String name;
2020

2121
@Schema(description = "스터디장 닉네임", example = "너굴")
22-
private String leaderNickname;
22+
private final String leaderNickname;
2323

2424
@Schema(description = "정원", example = "4")
25-
private int capacity;
25+
private final int capacity;
2626

2727
@Schema(description = "인원수", example = "3")
28-
private int currentCount;
28+
private final int currentCount;
2929

3030
@Schema(description = "시작일", example = "2025-07-15")
31-
private LocalDateTime startDate;
31+
private final LocalDateTime startDate;
3232

3333
@Schema(description = "대표 이미지", example = "http://localhost:8083/image.jpg")
34-
private String imageUrl;
34+
private final String imageUrl;
3535

3636
@Schema(description = "스터디 소개", example = "자바 스터디입니다.")
37-
private String introduction;
37+
private final String introduction;
3838

3939
@Schema(description = "카테고리", example = "IT")
40-
private Category category;
40+
private final Category category;
4141

4242
@Schema(description = "타입", example = "ONLINE")
43-
private StudyType studyType;
43+
final StudyType studyType;
4444

4545
@Schema(description = "열람 여부", example = "true")
46-
private boolean isRead;
46+
private final boolean isRead;
4747

4848
@Schema(description = "신청 상태", example = "PENDING")
49-
private ApplicationStatus status;
49+
private final ApplicationStatus status;
5050

5151
@QueryProjection
5252
public MyApplicationResponse(Long recruitmentPostId, String name, String leaderNickname, int capacity, int currentCount, LocalDateTime startDate,

src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/ReceivedApplicationPagingResponse.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,24 @@ public class ReceivedApplicationPagingResponse {
1414
description = "내 모집글에 지원한 신청 목록",
1515
example = "[{" +
1616
"\"applicationId\": 1," +
17+
"\"userId\": 1," +
1718
"\"nickname\": \"너굴\"," +
1819
"\"profileImageUrl\": \"http://localhost:8083/image.jpg\"," +
1920
"\"buddyEnergy\": 30," +
2021
"\"createdDate\": \"2025-07-10T15:30:00\"," +
2122
"\"applicationReason\": \"자바를 더 공부하고 싶어 지원합니다.\"" +
2223
"}]"
2324
)
24-
private List<ReceivedApplicationResponse> receivedApplications;
25+
private final List<ReceivedApplicationResponse> receivedApplications;
2526

2627
@Schema(description = "총 페이지 수", example = "2")
27-
private int totalPage;
28+
private final int totalPage;
2829

2930
@Schema(description = "총 요소 개수", example = "10")
30-
private int totalElementCount;
31+
private final int totalElementCount;
3132

3233
@Schema(description = "다음 페이지 여부", example = "false")
33-
private boolean hasNext;
34+
private final boolean hasNext;
3435

3536
@Builder
3637
private ReceivedApplicationPagingResponse(Page<ReceivedApplicationResponse> page) {

src/main/java/grep/neogulcoder/domain/studyapplication/controller/dto/response/ReceivedApplicationResponse.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,30 @@
1010
public class ReceivedApplicationResponse {
1111

1212
@Schema(description = "신청 번호", example = "1")
13-
private Long applicationId;
13+
private final Long applicationId;
14+
15+
@Schema(description = "신청자 번호", example = "1")
16+
private final Long userId;
1417

1518
@Schema(description = "신청자 닉네임", example = "너굴")
16-
private String nickname;
19+
private final String nickname;
1720

1821
@Schema(description = "신청자 프로필 이미지 URL", example = "http://localhost:8083/image.jpg")
19-
private String profileImageUrl;
22+
private final String profileImageUrl;
2023

2124
@Schema(description = "신청자 버디에너지", example = "30")
22-
private int buddyEnergy;
25+
private final int buddyEnergy;
2326

2427
@Schema(description = "신청 날짜", example = "2025-07-10T15:30:00")
25-
private LocalDateTime createdDate;
28+
private final LocalDateTime createdDate;
2629

2730
@Schema(description = "스터디 신청 지원 동기", example = "자바를 더 공부하고 싶어 지원합니다.")
28-
private String applicationReason;
31+
private final String applicationReason;
2932

3033
@QueryProjection
31-
public ReceivedApplicationResponse(Long applicationId, String nickname, String profileImageUrl, int buddyEnergy, LocalDateTime createdDate, String applicationReason) {
34+
public ReceivedApplicationResponse(Long applicationId, Long userId, String nickname, String profileImageUrl, int buddyEnergy, LocalDateTime createdDate, String applicationReason) {
3235
this.applicationId = applicationId;
36+
this.userId = userId;
3337
this.nickname = nickname;
3438
this.profileImageUrl = profileImageUrl;
3539
this.buddyEnergy = buddyEnergy;

src/main/java/grep/neogulcoder/domain/studyapplication/provider/ApplicationApprovedMessageProvider.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package grep.neogulcoder.domain.studyapplication.provider;
22

3-
import grep.neogulcoder.domain.alram.type.*;
3+
import grep.neogulcoder.domain.alram.type.AlarmType;
4+
import grep.neogulcoder.domain.alram.type.DomainType;
45
import grep.neogulcoder.domain.recruitment.post.RecruitmentPost;
56
import grep.neogulcoder.domain.recruitment.post.repository.RecruitmentPostRepository;
67
import grep.neogulcoder.domain.studyapplication.StudyApplication;
@@ -10,8 +11,8 @@
1011
import lombok.RequiredArgsConstructor;
1112
import org.springframework.stereotype.Component;
1213

13-
import static grep.neogulcoder.domain.recruitment.RecruitmentErrorCode.*;
14-
import static grep.neogulcoder.domain.studyapplication.exception.code.ApplicationErrorCode.*;
14+
import static grep.neogulcoder.domain.recruitment.RecruitmentErrorCode.NOT_FOUND;
15+
import static grep.neogulcoder.domain.studyapplication.exception.code.ApplicationErrorCode.APPLICATION_NOT_FOUND;
1516

1617
@Component
1718
@RequiredArgsConstructor

src/main/java/grep/neogulcoder/domain/studyapplication/provider/ApplicationMessageProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import lombok.RequiredArgsConstructor;
1010
import org.springframework.stereotype.Component;
1111

12-
import static grep.neogulcoder.domain.recruitment.RecruitmentErrorCode.*;
12+
import static grep.neogulcoder.domain.recruitment.RecruitmentErrorCode.NOT_FOUND;
1313

1414
@Component
1515
@RequiredArgsConstructor

0 commit comments

Comments
 (0)