Skip to content

Commit fd60791

Browse files
authored
refactor: 변경된 멘토/멘티 탭 명세에 맞게 api 수정 (#422)
* refactor: 변경된 api 명세에 맞게 컨트롤러 수정 * feat: 멘토링 목록 조회 페이지네이션 적용 - 추가로 N+1 해결 * test: 페이지네이션으로 바뀐 것 테스트코드에 적용 - 추가로, 멘토링에 mentor_id와 mentee_id가 unique 해야 할 것을 염두에 두고, 테스트 코드 수정 - 테스트 단위가 작아지도록 수정 * refactor: 멘토링 체크 로직 서비스 분리 * refactor: 멘토링 테이블에 checked_at_by_mentee 컬럼 추가 * feat: 멘토,멘티의 멘토링 확인 기능 구현 * test: 멘토링 목록 조회 시, 확인여부 포함 검증 추가 * refactor: 멘토가 승인하면, 멘티의 멘토링 확인상태 초기화 * refactor: 멘티가 거절된 멘토링 조회하지 못하도록
1 parent 88ef936 commit fd60791

18 files changed

+669
-174
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.example.solidconnection.mentor.controller;
2+
3+
import com.example.solidconnection.common.VerifyStatus;
4+
import com.example.solidconnection.common.dto.SliceResponse;
5+
import com.example.solidconnection.common.resolver.AuthorizedUser;
6+
import com.example.solidconnection.mentor.dto.CheckMentoringRequest;
7+
import com.example.solidconnection.mentor.dto.CheckedMentoringsResponse;
8+
import com.example.solidconnection.mentor.dto.MentoringApplyRequest;
9+
import com.example.solidconnection.mentor.dto.MentoringApplyResponse;
10+
import com.example.solidconnection.mentor.dto.MentoringForMenteeResponse;
11+
import com.example.solidconnection.mentor.service.MentoringCheckService;
12+
import com.example.solidconnection.mentor.service.MentoringCommandService;
13+
import com.example.solidconnection.mentor.service.MentoringQueryService;
14+
import com.example.solidconnection.security.annotation.RequireRoleAccess;
15+
import com.example.solidconnection.siteuser.domain.Role;
16+
import jakarta.validation.Valid;
17+
import lombok.RequiredArgsConstructor;
18+
import org.springframework.data.domain.Pageable;
19+
import org.springframework.data.domain.Sort;
20+
import org.springframework.data.web.PageableDefault;
21+
import org.springframework.data.web.SortDefault;
22+
import org.springframework.data.web.SortDefault.SortDefaults;
23+
import org.springframework.http.ResponseEntity;
24+
import org.springframework.web.bind.annotation.GetMapping;
25+
import org.springframework.web.bind.annotation.PatchMapping;
26+
import org.springframework.web.bind.annotation.PostMapping;
27+
import org.springframework.web.bind.annotation.RequestBody;
28+
import org.springframework.web.bind.annotation.RequestMapping;
29+
import org.springframework.web.bind.annotation.RequestParam;
30+
import org.springframework.web.bind.annotation.RestController;
31+
32+
@RestController
33+
@RequiredArgsConstructor
34+
@RequestMapping("/mentee/mentorings")
35+
public class MentoringForMenteeController {
36+
37+
private final MentoringCommandService mentoringCommandService;
38+
private final MentoringQueryService mentoringQueryService;
39+
private final MentoringCheckService mentoringCheckService;
40+
41+
@RequireRoleAccess(roles = Role.MENTEE)
42+
@PostMapping
43+
public ResponseEntity<MentoringApplyResponse> applyMentoring(
44+
@AuthorizedUser long siteUserId,
45+
@Valid @RequestBody MentoringApplyRequest mentoringApplyRequest
46+
) {
47+
MentoringApplyResponse response = mentoringCommandService.applyMentoring(siteUserId, mentoringApplyRequest);
48+
return ResponseEntity.ok(response);
49+
}
50+
51+
@RequireRoleAccess(roles = Role.MENTEE)
52+
@GetMapping
53+
public ResponseEntity<SliceResponse<MentoringForMenteeResponse>> getMentorings(
54+
@AuthorizedUser long siteUserId,
55+
@RequestParam("verify-status") VerifyStatus verifyStatus,
56+
@PageableDefault(size = 3)
57+
@SortDefaults({
58+
@SortDefault(sort = "createdAt", direction = Sort.Direction.DESC),
59+
@SortDefault(sort = "id", direction = Sort.Direction.DESC)
60+
})
61+
Pageable pageable
62+
) {
63+
SliceResponse<MentoringForMenteeResponse> response = mentoringQueryService.getMentoringsForMentee(siteUserId, verifyStatus, pageable);
64+
return ResponseEntity.ok(response);
65+
}
66+
67+
@RequireRoleAccess(roles = {Role.MENTEE})
68+
@PatchMapping("/check")
69+
public ResponseEntity<CheckedMentoringsResponse> checkMentorings(
70+
@AuthorizedUser long siteUserId,
71+
@Valid @RequestBody CheckMentoringRequest checkMentoringRequest
72+
) {
73+
CheckedMentoringsResponse response = mentoringCheckService.checkMentoringsForMentee(siteUserId, checkMentoringRequest);
74+
return ResponseEntity.ok(response);
75+
}
76+
}

src/main/java/com/example/solidconnection/mentor/controller/MentoringController.java renamed to src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,59 @@
11
package com.example.solidconnection.mentor.controller;
22

3+
import com.example.solidconnection.common.dto.SliceResponse;
34
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;
5+
import com.example.solidconnection.mentor.dto.CheckMentoringRequest;
6+
import com.example.solidconnection.mentor.dto.CheckedMentoringsResponse;
77
import com.example.solidconnection.mentor.dto.MentoringConfirmRequest;
88
import com.example.solidconnection.mentor.dto.MentoringConfirmResponse;
99
import com.example.solidconnection.mentor.dto.MentoringCountResponse;
10-
import com.example.solidconnection.mentor.dto.MentoringListResponse;
10+
import com.example.solidconnection.mentor.dto.MentoringForMentorResponse;
11+
import com.example.solidconnection.mentor.service.MentoringCheckService;
1112
import com.example.solidconnection.mentor.service.MentoringCommandService;
1213
import com.example.solidconnection.mentor.service.MentoringQueryService;
1314
import com.example.solidconnection.security.annotation.RequireRoleAccess;
1415
import com.example.solidconnection.siteuser.domain.Role;
1516
import jakarta.validation.Valid;
1617
import lombok.RequiredArgsConstructor;
18+
import org.springframework.data.domain.Pageable;
19+
import org.springframework.data.domain.Sort;
20+
import org.springframework.data.web.PageableDefault;
21+
import org.springframework.data.web.SortDefault;
22+
import org.springframework.data.web.SortDefault.SortDefaults;
1723
import org.springframework.http.ResponseEntity;
1824
import org.springframework.web.bind.annotation.GetMapping;
1925
import org.springframework.web.bind.annotation.PatchMapping;
2026
import org.springframework.web.bind.annotation.PathVariable;
21-
import org.springframework.web.bind.annotation.PostMapping;
2227
import org.springframework.web.bind.annotation.RequestBody;
2328
import org.springframework.web.bind.annotation.RequestMapping;
2429
import org.springframework.web.bind.annotation.RestController;
2530

2631
@RestController
2732
@RequiredArgsConstructor
28-
@RequestMapping("/mentorings")
29-
public class MentoringController {
33+
@RequestMapping("/mentor/mentorings")
34+
public class MentoringForMentorController {
3035

3136
private final MentoringCommandService mentoringCommandService;
3237
private final MentoringQueryService mentoringQueryService;
38+
private final MentoringCheckService mentoringCheckService;
3339

34-
@RequireRoleAccess(roles = Role.MENTEE)
35-
@PostMapping("/apply")
36-
public ResponseEntity<MentoringApplyResponse> applyMentoring(
40+
@RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR})
41+
@GetMapping
42+
public ResponseEntity<SliceResponse<MentoringForMentorResponse>> getMentorings(
3743
@AuthorizedUser long siteUserId,
38-
@Valid @RequestBody MentoringApplyRequest mentoringApplyRequest
44+
@PageableDefault(size = 3)
45+
@SortDefaults({
46+
@SortDefault(sort = "createdAt", direction = Sort.Direction.DESC),
47+
@SortDefault(sort = "id", direction = Sort.Direction.DESC)
48+
})
49+
Pageable pageable
3950
) {
40-
MentoringApplyResponse response = mentoringCommandService.applyMentoring(siteUserId, mentoringApplyRequest);
51+
SliceResponse<MentoringForMentorResponse> response = mentoringQueryService.getMentoringsForMentor(siteUserId, pageable);
4152
return ResponseEntity.ok(response);
4253
}
4354

4455
@RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR})
45-
@GetMapping("/apply")
46-
public ResponseEntity<MentoringListResponse> getMentorings(
47-
@AuthorizedUser long siteUserId
48-
) {
49-
MentoringListResponse responses = mentoringQueryService.getMentorings(siteUserId);
50-
return ResponseEntity.ok(responses);
51-
}
52-
53-
@RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR})
54-
@PatchMapping("/{mentoring-id}/apply")
56+
@PatchMapping("/{mentoring-id}")
5557
public ResponseEntity<MentoringConfirmResponse> confirmMentoring(
5658
@AuthorizedUser long siteUserId,
5759
@PathVariable("mentoring-id") Long mentoringId,
@@ -62,12 +64,12 @@ public ResponseEntity<MentoringConfirmResponse> confirmMentoring(
6264
}
6365

6466
@RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR})
65-
@PatchMapping("/{mentoring-id}/check")
66-
public ResponseEntity<MentoringCheckResponse> checkMentoring(
67+
@PatchMapping("/check")
68+
public ResponseEntity<CheckedMentoringsResponse> checkMentoring(
6769
@AuthorizedUser long siteUserId,
68-
@PathVariable("mentoring-id") Long mentoringId
70+
@RequestBody CheckMentoringRequest mentoringCheckRequest
6971
) {
70-
MentoringCheckResponse response = mentoringCommandService.checkMentoring(siteUserId, mentoringId);
72+
CheckedMentoringsResponse response = mentoringCheckService.checkMentoringsForMentor(siteUserId, mentoringCheckRequest);
7173
return ResponseEntity.ok(response);
7274
}
7375

@@ -76,7 +78,7 @@ public ResponseEntity<MentoringCheckResponse> checkMentoring(
7678
public ResponseEntity<MentoringCountResponse> getUncheckedMentoringsCount(
7779
@AuthorizedUser long siteUserId
7880
) {
79-
MentoringCountResponse response = mentoringQueryService.getNewMentoringsCount(siteUserId);
81+
MentoringCountResponse response = mentoringCheckService.getUncheckedMentoringCount(siteUserId);
8082
return ResponseEntity.ok(response);
8183
}
8284
}

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ public class Mentoring {
4040
private ZonedDateTime confirmedAt;
4141

4242
@Column
43-
private ZonedDateTime checkedAt;
43+
private ZonedDateTime checkedAtByMentor;
44+
45+
@Column
46+
private ZonedDateTime checkedAtByMentee;
4447

4548
@Column(nullable = false)
4649
@Enumerated(EnumType.STRING)
@@ -67,12 +70,19 @@ public void confirm(VerifyStatus status) {
6770
this.verifyStatus = status;
6871
this.confirmedAt = ZonedDateTime.now(UTC).truncatedTo(MICROS);
6972

70-
if (this.checkedAt == null) {
71-
this.checkedAt = this.confirmedAt;
73+
if (this.checkedAtByMentor == null) {
74+
this.checkedAtByMentor = this.confirmedAt;
75+
}
76+
if (this.checkedAtByMentee != null) {
77+
this.checkedAtByMentee = null;
7278
}
7379
}
7480

75-
public void check() {
76-
this.checkedAt = ZonedDateTime.now(UTC).truncatedTo(MICROS);
81+
public void checkByMentor() {
82+
this.checkedAtByMentor = ZonedDateTime.now(UTC).truncatedTo(MICROS);
83+
}
84+
85+
public void checkByMentee() {
86+
this.checkedAtByMentee = ZonedDateTime.now(UTC).truncatedTo(MICROS);
7787
}
7888
}
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 java.util.List;
4+
5+
public record CheckMentoringRequest(
6+
List<Long> checkedMentoringIds
7+
) {
8+
9+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.example.solidconnection.mentor.dto;
2+
3+
import com.example.solidconnection.mentor.domain.Mentoring;
4+
import java.util.List;
5+
6+
public record CheckedMentoringsResponse(
7+
List<Long> checkedMentoringIds
8+
) {
9+
10+
public static CheckedMentoringsResponse from(List<Mentoring> mentorings) {
11+
return new CheckedMentoringsResponse(
12+
mentorings.stream().map(Mentoring::getId).toList()
13+
);
14+
}
15+
}

src/main/java/com/example/solidconnection/mentor/dto/MentoringResponse.java renamed to src/main/java/com/example/solidconnection/mentor/dto/MentoringForMenteeResponse.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@
44
import com.example.solidconnection.siteuser.domain.SiteUser;
55
import java.time.ZonedDateTime;
66

7-
public record MentoringResponse(
7+
public record MentoringForMenteeResponse(
88
long mentoringId,
99
String profileImageUrl,
1010
String nickname,
1111
boolean isChecked,
1212
ZonedDateTime createdAt
1313
) {
1414

15-
public static MentoringResponse from(Mentoring mentoring, SiteUser mentee) {
16-
return new MentoringResponse(
15+
public static MentoringForMenteeResponse of(Mentoring mentoring, SiteUser partner) {
16+
return new MentoringForMenteeResponse(
1717
mentoring.getId(),
18-
mentee.getProfileImageUrl(),
19-
mentee.getNickname(),
20-
mentoring.getCheckedAt() != null,
18+
partner.getProfileImageUrl(),
19+
partner.getNickname(),
20+
mentoring.getCheckedAtByMentee() != null,
2121
mentoring.getCreatedAt()
2222
);
2323
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.example.solidconnection.mentor.dto;
2+
3+
import com.example.solidconnection.mentor.domain.Mentoring;
4+
import com.example.solidconnection.siteuser.domain.SiteUser;
5+
import java.time.ZonedDateTime;
6+
7+
public record MentoringForMentorResponse(
8+
long mentoringId,
9+
String profileImageUrl,
10+
String nickname,
11+
boolean isChecked,
12+
ZonedDateTime createdAt
13+
) {
14+
15+
public static MentoringForMentorResponse of(Mentoring mentoring, SiteUser partner) {
16+
return new MentoringForMentorResponse(
17+
mentoring.getId(),
18+
partner.getProfileImageUrl(),
19+
partner.getNickname(),
20+
mentoring.getCheckedAtByMentor() != null,
21+
mentoring.getCreatedAt()
22+
);
23+
}
24+
}

src/main/java/com/example/solidconnection/mentor/dto/MentoringListResponse.java

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
package com.example.solidconnection.mentor.repository;
22

3+
import com.example.solidconnection.common.VerifyStatus;
34
import com.example.solidconnection.mentor.domain.Mentoring;
45
import java.util.List;
6+
import org.springframework.data.domain.Pageable;
7+
import org.springframework.data.domain.Slice;
58
import org.springframework.data.jpa.repository.JpaRepository;
69
import org.springframework.data.jpa.repository.Query;
710
import org.springframework.data.repository.query.Param;
811

912
public interface MentoringRepository extends JpaRepository<Mentoring, Long> {
1013

11-
int countByMentorIdAndCheckedAtIsNull(long mentorId);
14+
int countByMentorIdAndCheckedAtByMentorIsNull(long mentorId);
1215

1316
boolean existsByMentorIdAndMenteeId(long mentorId, long menteeId);
1417

15-
List<Mentoring> findAllByMentorId(long mentorId);
18+
Slice<Mentoring> findAllByMentorId(long mentorId, Pageable pageable);
19+
20+
@Query("""
21+
SELECT m FROM Mentoring m
22+
WHERE m.menteeId = :menteeId AND m.verifyStatus = :verifyStatus
23+
""")
24+
Slice<Mentoring> findAllByMenteeIdAndVerifyStatus(@Param("menteeId") long menteeId, @Param("verifyStatus") VerifyStatus verifyStatus, Pageable pageable);
1625

1726
@Query("""
1827
SELECT m FROM Mentoring m

0 commit comments

Comments
 (0)