Skip to content

Commit 7ef425a

Browse files
authored
feat: 멘토링 관련 도메인 추가 (#362)
* feat: 멘토링 신청 구현 * feat: 멘토링 요청 목록 조회, 멘토링 수락/거절 구현 * feat: 멘토링 확인 구현 * feat: 멘토링 신규 신청 건수 조회 구현 * chore: 전반적으로 로직 수정 - 통일성 있게 .ok(response) 사용 - 단일 객체는 단수형(response) 사용 * chore: 불필요한 개행 제거 * chore: rebase 시 반영되지 않는 로직 추가 * chore: 멘토 관련 로직에 권한 부여 * test: 멘토 관련 픽스처 생성 * test: 멘토링 조회 서비스 테스트 구현 * fix: 이미 멘토인 사용자 검증 로직 수정 - 파라미터는 siteUserId이므로 이를 통해 멘토 존재 여부를 구해야 함. * chore: 멘토가 자기 자신에 대해 멘토링을 신청하는 경우 검증 삭제 - 멘토링을 신청하는 사용자가 멘토인지 여부로 검증 가능 * chore: 미사용 테스트 메서드 삭제 * test: 멘토링 CUD 테스트 구현 * refactor: List 자체를 Response로 리턴하도록 수정 * refactor: Long -> long으로 변경 * refactor: 개행 추가 * refactor: 처음 개행 추가, Long -> long * refactor: 메서드 간 개행 추가 * chore: 불필요한 테스트 코드 제거 * refactor: 테스트 코드 리팩터링 - import 문 개행 추가 - 테스트 이름 컨벤션 준수하도록 변경 * refactor: 컨벤션에 맞게 코드 수정 - private 함수는 마지막으로 사용되는 public 함수 아래에 작성한다. - Long -> long * refactor: 비즈니스 로직 흐름에 맞게 순서 변경 * chore: 코드 컨벤션 따르도록 수정 - DTO 첫 개행 제거 - import 문 개행 수정 * refactor: 멘토 여부 검증을 서비스 말고 컨트롤러에서 처리하도록 수정 - RequireRoleAccess 어노테이션을 사용하여 멘티 여부 검증 * chore: 컨벤션 관련 수정 - Long -> long - 의미에 맞도록 서비스 계층의 validate 함수명 변경 * refactor: API 명세에 맞게 응답 수정 * chore: 오타 수정 * refactor: 빌더 패턴 제거 * chore: validateMentoringOwnership 메서드 바디 수정 - 주석의 내용을 잘 대변하도록 변경 * chore: 코딩 컨벤션에 맞도록 수정 - 파라미터 3개인 경우 개행하지 않는다 - 적절한 이름으로 컨트롤러 메서드명 수정 * chore: 코딩 컨벤션에 맞도록 수정 - 적절한 이름으로 컨트롤러 메서드명 수정 * chore: 코딩 컨벤션에 맞도록 수정 - 불필요한 개행 제거
1 parent fe7aefc commit 7ef425a

22 files changed

+957
-0
lines changed

src/main/java/com/example/solidconnection/common/exception/ErrorCode.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ public enum ErrorCode {
104104
// database
105105
DATA_INTEGRITY_VIOLATION(HttpStatus.CONFLICT.value(), "데이터베이스 무결성 제약조건 위반이 발생했습니다."),
106106

107+
// mentor
108+
ALREADY_MENTOR(HttpStatus.BAD_REQUEST.value(), "이미 멘토로 등록된 사용자입니다."),
109+
MENTOR_NOT_FOUND(HttpStatus.NOT_FOUND.value(), "해당 사용자는 멘토로 등록되어 있지 않습니다."),
110+
MENTORING_NOT_FOUND(HttpStatus.NOT_FOUND.value(), "해당 멘토링 신청을 찾을 수 없습니다."),
111+
UNAUTHORIZED_MENTORING(HttpStatus.FORBIDDEN.value(), "멘토링 권한이 없습니다."),
112+
MENTORING_ALREADY_CONFIRMED(HttpStatus.BAD_REQUEST.value(), "이미 승인 또는 거절된 멘토링입니다."),
113+
107114
// general
108115
JSON_PARSING_FAILED(HttpStatus.BAD_REQUEST.value(), "JSON 파싱을 할 수 없습니다."),
109116
JWT_EXCEPTION(HttpStatus.BAD_REQUEST.value(), "JWT 토큰을 처리할 수 없습니다."),
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.example.solidconnection.mentor.controller;
2+
3+
import com.example.solidconnection.common.resolver.AuthorizedUser;
4+
import com.example.solidconnection.mentor.dto.MentoringApplyRequest;
5+
import com.example.solidconnection.mentor.dto.MentoringApplyResponse;
6+
import com.example.solidconnection.mentor.dto.MentoringCheckResponse;
7+
import com.example.solidconnection.mentor.dto.MentoringConfirmRequest;
8+
import com.example.solidconnection.mentor.dto.MentoringConfirmResponse;
9+
import com.example.solidconnection.mentor.dto.MentoringCountResponse;
10+
import com.example.solidconnection.mentor.dto.MentoringListResponse;
11+
import com.example.solidconnection.mentor.service.MentoringCommandService;
12+
import com.example.solidconnection.mentor.service.MentoringQueryService;
13+
import com.example.solidconnection.security.annotation.RequireRoleAccess;
14+
import com.example.solidconnection.siteuser.domain.Role;
15+
import com.example.solidconnection.siteuser.domain.SiteUser;
16+
import jakarta.validation.Valid;
17+
import lombok.RequiredArgsConstructor;
18+
import org.springframework.http.ResponseEntity;
19+
import org.springframework.web.bind.annotation.GetMapping;
20+
import org.springframework.web.bind.annotation.PatchMapping;
21+
import org.springframework.web.bind.annotation.PathVariable;
22+
import org.springframework.web.bind.annotation.PostMapping;
23+
import org.springframework.web.bind.annotation.RequestBody;
24+
import org.springframework.web.bind.annotation.RequestMapping;
25+
import org.springframework.web.bind.annotation.RestController;
26+
27+
@RestController
28+
@RequiredArgsConstructor
29+
@RequestMapping("/mentorings")
30+
public class MentoringController {
31+
32+
private final MentoringCommandService mentoringCommandService;
33+
private final MentoringQueryService mentoringQueryService;
34+
35+
@RequireRoleAccess(roles = Role.MENTEE)
36+
@PostMapping("/apply")
37+
public ResponseEntity<MentoringApplyResponse> applyMentoring(
38+
@AuthorizedUser SiteUser siteUser,
39+
@Valid @RequestBody MentoringApplyRequest mentoringApplyRequest
40+
) {
41+
MentoringApplyResponse response = mentoringCommandService.applyMentoring(siteUser.getId(), mentoringApplyRequest);
42+
return ResponseEntity.ok(response);
43+
}
44+
45+
@RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR})
46+
@GetMapping("/apply")
47+
public ResponseEntity<MentoringListResponse> getMentorings(
48+
@AuthorizedUser SiteUser siteUser
49+
) {
50+
MentoringListResponse responses = mentoringQueryService.getMentorings(siteUser.getId());
51+
return ResponseEntity.ok(responses);
52+
}
53+
54+
@RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR})
55+
@PatchMapping("/{mentoring-id}/apply")
56+
public ResponseEntity<MentoringConfirmResponse> confirmMentoring(
57+
@AuthorizedUser SiteUser siteUser,
58+
@PathVariable("mentoring-id") Long mentoringId,
59+
@Valid @RequestBody MentoringConfirmRequest mentoringConfirmRequest
60+
) {
61+
MentoringConfirmResponse response = mentoringCommandService.confirmMentoring(siteUser.getId(), mentoringId, mentoringConfirmRequest);
62+
return ResponseEntity.ok(response);
63+
}
64+
65+
@RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR})
66+
@PatchMapping("/{mentoring-id}/check")
67+
public ResponseEntity<MentoringCheckResponse> checkMentoring(
68+
@AuthorizedUser SiteUser siteUser,
69+
@PathVariable("mentoring-id") Long mentoringId
70+
) {
71+
MentoringCheckResponse response = mentoringCommandService.checkMentoring(siteUser.getId(), mentoringId);
72+
return ResponseEntity.ok(response);
73+
}
74+
75+
@RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR})
76+
@GetMapping("/check")
77+
public ResponseEntity<MentoringCountResponse> getUncheckedMentoringsCount(
78+
@AuthorizedUser SiteUser siteUser
79+
) {
80+
MentoringCountResponse response = mentoringQueryService.getNewMentoringsCount(siteUser.getId());
81+
return ResponseEntity.ok(response);
82+
}
83+
}

src/main/java/com/example/solidconnection/mentor/domain/Mentor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,8 @@ public class Mentor {
4545

4646
@OneToMany(mappedBy = "mentor", cascade = CascadeType.ALL, orphanRemoval = true)
4747
private List<Channel> channels = new ArrayList<>();
48+
49+
public void increaseMenteeCount() {
50+
this.menteeCount++;
51+
}
4852
}

src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,28 @@ public class Mentoring {
5656
@Column
5757
private long menteeId;
5858

59+
public Mentoring(long mentorId, long menteeId, VerifyStatus verifyStatus) {
60+
this.mentorId = mentorId;
61+
this.menteeId = menteeId;
62+
this.verifyStatus = verifyStatus;
63+
}
64+
5965
@PrePersist
6066
public void onPrePersist() {
6167
this.createdAt = ZonedDateTime.now(UTC).truncatedTo(MICROS); // 나노초 6자리 까지만 저장
6268
}
69+
70+
public void confirm(VerifyStatus status, String rejectedReason) {
71+
this.verifyStatus = status;
72+
this.rejectedReason = rejectedReason;
73+
this.confirmedAt = ZonedDateTime.now(UTC).truncatedTo(MICROS);
74+
75+
if (this.checkedAt == null) {
76+
this.checkedAt = this.confirmedAt;
77+
}
78+
}
79+
80+
public void check() {
81+
this.checkedAt = ZonedDateTime.now(UTC).truncatedTo(MICROS);
82+
}
6383
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.example.solidconnection.mentor.dto;
2+
3+
import jakarta.validation.constraints.NotNull;
4+
5+
public record MentoringApplyRequest(
6+
@NotNull(message = "멘토 id를 입력해주세요.")
7+
Long mentorId
8+
) {
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.example.solidconnection.mentor.dto;
2+
3+
import com.example.solidconnection.mentor.domain.Mentoring;
4+
5+
public record MentoringApplyResponse(
6+
long mentoringId
7+
) {
8+
9+
public static MentoringApplyResponse from(Mentoring mentoring) {
10+
return new MentoringApplyResponse(mentoring.getId());
11+
}
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.example.solidconnection.mentor.dto;
2+
3+
public record MentoringCheckResponse(
4+
long mentoringId
5+
) {
6+
7+
public static MentoringCheckResponse from(long mentoringId) {
8+
return new MentoringCheckResponse(mentoringId);
9+
}
10+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.example.solidconnection.mentor.dto;
2+
3+
import com.example.solidconnection.common.VerifyStatus;
4+
import jakarta.validation.constraints.NotNull;
5+
6+
public record MentoringConfirmRequest(
7+
@NotNull(message = "승인 상태를 설정해주세요.")
8+
VerifyStatus status,
9+
10+
String rejectedReason
11+
) {
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.example.solidconnection.mentor.dto;
2+
3+
import com.example.solidconnection.mentor.domain.Mentoring;
4+
5+
public record MentoringConfirmResponse(
6+
long mentoringId
7+
) {
8+
public static MentoringConfirmResponse from(Mentoring mentoring) {
9+
return new MentoringConfirmResponse(mentoring.getId());
10+
}
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.example.solidconnection.mentor.dto;
2+
3+
public record MentoringCountResponse(
4+
int uncheckedCount
5+
) {
6+
7+
public static MentoringCountResponse from(int uncheckedCount) {
8+
return new MentoringCountResponse(uncheckedCount);
9+
}
10+
}

0 commit comments

Comments
 (0)