Skip to content

Commit 7e7ab91

Browse files
authored
Merge pull request #134 from prgrms-web-devcourse-final-project/develop
4차 메인 머지(10/1)
2 parents bc2e837 + 095b7e0 commit 7e7ab91

File tree

49 files changed

+1650
-392
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1650
-392
lines changed

back/src/main/java/com/back/domain/member/member/service/MemberStorage.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
import lombok.RequiredArgsConstructor;
1111
import org.springframework.stereotype.Component;
1212

13-
import java.util.Optional;
14-
1513
@Component
1614
@RequiredArgsConstructor
1715
public class MemberStorage {
@@ -29,9 +27,6 @@ public Mentor findMentorByMemberId(Long memberId) {
2927
return mentorRepository.findByMemberIdWithMember(memberId)
3028
.orElseThrow(() -> new ServiceException(MemberErrorCode.NOT_FOUND_MENTOR));
3129
}
32-
public Optional<Mentor> findMentorByMemberOptional(Member member) {
33-
return mentorRepository.findByMemberIdWithMember(member.getId());
34-
}
3530

3631
public Mentee findMenteeByMember(Member member) {
3732
return menteeRepository.findByMemberIdWithMember(member.getId())

back/src/main/java/com/back/domain/member/mentee/entity/Mentee.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,8 @@ public Mentee(Member member, Long jobId) {
3131
public void delete() {
3232
this.isDeleted = true;
3333
}
34+
35+
public boolean isMember(Member member) {
36+
return this.member.equals(member);
37+
}
3438
}

back/src/main/java/com/back/domain/member/mentor/entity/Mentor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,8 @@ public void updateCareerYears(Integer careerYears) {
4343
public void delete() {
4444
this.isDeleted = true;
4545
}
46+
47+
public boolean isMember(Member member) {
48+
return this.member.equals(member);
49+
}
4650
}

back/src/main/java/com/back/domain/mentoring/mentoring/dto/MentoringWithTagsDto.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@ public record MentoringWithTagsDto(
1111
@Schema(description = "멘토링 제목")
1212
String title,
1313
@Schema(description = "멘토링 태그")
14-
List<String> tags
14+
List<String> tags,
15+
@Schema(description = "멘토 ID")
16+
Long mentorId,
17+
@Schema(description = "멘토 닉네임")
18+
String nickname
1519
) {
1620
public static MentoringWithTagsDto from(Mentoring mentoring) {
1721
return new MentoringWithTagsDto(
1822
mentoring.getId(),
1923
mentoring.getTitle(),
20-
mentoring.getTags()
24+
mentoring.getTags(),
25+
mentoring.getMentor().getId(),
26+
mentoring.getMentor().getMember().getNickname()
2127
);
2228
}
2329
}

back/src/main/java/com/back/domain/mentoring/reservation/controller/ReservationController.java

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import com.back.domain.member.member.service.MemberStorage;
55
import com.back.domain.member.mentee.entity.Mentee;
66
import com.back.domain.member.mentor.entity.Mentor;
7+
import com.back.domain.mentoring.reservation.dto.ReservationDto;
78
import com.back.domain.mentoring.reservation.dto.request.ReservationRequest;
9+
import com.back.domain.mentoring.reservation.dto.response.ReservationPagingResponse;
810
import com.back.domain.mentoring.reservation.dto.response.ReservationResponse;
911
import com.back.domain.mentoring.reservation.service.ReservationService;
1012
import com.back.global.rq.Rq;
@@ -13,11 +15,10 @@
1315
import io.swagger.v3.oas.annotations.tags.Tag;
1416
import jakarta.validation.Valid;
1517
import lombok.RequiredArgsConstructor;
18+
import org.springframework.data.domain.Page;
1619
import org.springframework.security.access.prepost.PreAuthorize;
1720
import org.springframework.web.bind.annotation.*;
1821

19-
import java.util.Optional;
20-
2122
@RestController
2223
@RequestMapping("/reservations")
2324
@RequiredArgsConstructor
@@ -28,14 +29,46 @@ public class ReservationController {
2829
private final ReservationService reservationService;
2930
private final MemberStorage memberStorage;
3031

32+
@GetMapping
33+
@Operation(summary = "나의 예약 목록 조회", description = "본인의 예약 목록을 조회합니다. 로그인 후 조회할 수 있습니다.")
34+
public RsData<ReservationPagingResponse> getReservations(
35+
@RequestParam(defaultValue = "0") int page,
36+
@RequestParam(defaultValue = "10") int size
37+
) {
38+
Member member = rq.getActor();
39+
Page<ReservationDto> reservationPage = reservationService.getReservations(member, page, size);
40+
ReservationPagingResponse resDto = ReservationPagingResponse.from(reservationPage);
41+
42+
return new RsData<>(
43+
"200",
44+
"예약 목록을 조회하였습니다.",
45+
resDto
46+
);
47+
}
48+
49+
50+
@GetMapping("/{reservationId}")
51+
@Operation(summary = "예약 조회", description = "특정 예약을 조회합니다. 로그인 후 예약 조회할 수 있습니다.")
52+
public RsData<ReservationResponse> getReservation(
53+
@PathVariable Long reservationId
54+
) {
55+
Member member = rq.getActor();
56+
ReservationResponse resDto = reservationService.getReservation(member, reservationId);
57+
58+
return new RsData<>(
59+
"200",
60+
"예약을 조회하였습니다.",
61+
resDto
62+
);
63+
}
64+
3165
@PostMapping
3266
@PreAuthorize("hasRole('MENTEE')")
3367
@Operation(summary = "예약 신청", description = "멘티가 멘토의 슬롯을 선택해 예약 신청을 합니다. 로그인한 멘티만 예약 신청할 수 있습니다.")
3468
public RsData<ReservationResponse> createReservation(
3569
@RequestBody @Valid ReservationRequest reqDto
3670
) {
3771
Mentee mentee = memberStorage.findMenteeByMember(rq.getActor());
38-
3972
ReservationResponse resDto = reservationService.createReservation(mentee, reqDto);
4073

4174
return new RsData<>(
@@ -52,7 +85,6 @@ public RsData<ReservationResponse> approveReservation(
5285
@PathVariable Long reservationId
5386
) {
5487
Mentor mentor = memberStorage.findMentorByMember(rq.getActor());
55-
5688
ReservationResponse resDto = reservationService.approveReservation(mentor, reservationId);
5789

5890
return new RsData<>(
@@ -69,7 +101,6 @@ public RsData<ReservationResponse> rejectReservation(
69101
@PathVariable Long reservationId
70102
) {
71103
Mentor mentor = memberStorage.findMentorByMember(rq.getActor());
72-
73104
ReservationResponse resDto = reservationService.rejectReservation(mentor, reservationId);
74105

75106
return new RsData<>(
@@ -85,15 +116,7 @@ public RsData<ReservationResponse> cancelReservation(
85116
@PathVariable Long reservationId
86117
) {
87118
Member member = rq.getActor();
88-
ReservationResponse resDto;
89-
90-
Optional<Mentor> mentor = memberStorage.findMentorByMemberOptional(member);
91-
if (mentor.isPresent()) {
92-
resDto = reservationService.cancelReservation(mentor.get(), reservationId);
93-
} else {
94-
Mentee mentee = memberStorage.findMenteeByMember(member);
95-
resDto = reservationService.cancelReservation(mentee, reservationId);
96-
}
119+
ReservationResponse resDto = reservationService.cancelReservation(member, reservationId);
97120

98121
return new RsData<>(
99122
"200",
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.back.domain.mentoring.reservation.dto;
2+
3+
import com.back.domain.mentoring.reservation.constant.ReservationStatus;
4+
import com.back.domain.mentoring.reservation.entity.Reservation;
5+
import io.swagger.v3.oas.annotations.media.Schema;
6+
7+
import java.time.LocalDateTime;
8+
9+
public record ReservationDto(
10+
@Schema(description = "예약 ID")
11+
Long reservationId,
12+
@Schema(description = "예약 상태")
13+
ReservationStatus status,
14+
15+
@Schema(description = "멘토링 ID")
16+
Long mentoringId,
17+
@Schema(description = "멘토링 제목")
18+
String title,
19+
20+
@Schema(description = "멘토 슬롯 ID")
21+
Long mentorSlotId,
22+
@Schema(description = "시작 일시")
23+
LocalDateTime startDateTime,
24+
@Schema(description = "종료 일시")
25+
LocalDateTime endDateTime
26+
) {
27+
public static ReservationDto from(Reservation reservation) {
28+
return new ReservationDto(
29+
reservation.getId(),
30+
reservation.getStatus(),
31+
reservation.getMentoring().getId(),
32+
reservation.getMentoring().getTitle(),
33+
reservation.getMentorSlot().getId(),
34+
reservation.getMentorSlot().getStartDateTime(),
35+
reservation.getMentorSlot().getEndDateTime()
36+
);
37+
}
38+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.back.domain.mentoring.reservation.dto.response;
2+
3+
import com.back.domain.mentoring.reservation.dto.ReservationDto;
4+
import io.swagger.v3.oas.annotations.media.Schema;
5+
import org.springframework.data.domain.Page;
6+
7+
import java.util.List;
8+
9+
public record ReservationPagingResponse(
10+
@Schema(description = "예약 목록")
11+
List<ReservationDto> reservations,
12+
@Schema(description = "현재 페이지 (0부터 시작)")
13+
int currentPage,
14+
@Schema(description = "총 페이지")
15+
int totalPage,
16+
@Schema(description = "총 개수")
17+
long totalElements,
18+
@Schema(description = "다음 페이지 존재 여부")
19+
boolean hasNext
20+
) {
21+
public static ReservationPagingResponse from(Page<ReservationDto> page) {
22+
return new ReservationPagingResponse(
23+
page.getContent(),
24+
page.getNumber(),
25+
page.getTotalPages(),
26+
page.getTotalElements(),
27+
page.hasNext()
28+
);
29+
}
30+
}

back/src/main/java/com/back/domain/mentoring/reservation/entity/Reservation.java

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.back.domain.mentoring.reservation.entity;
22

3+
import com.back.domain.member.member.entity.Member;
34
import com.back.domain.member.mentee.entity.Mentee;
45
import com.back.domain.member.mentor.entity.Mentor;
56
import com.back.domain.mentoring.mentoring.entity.Mentoring;
@@ -14,6 +15,13 @@
1415
import lombok.NoArgsConstructor;
1516

1617
@Entity
18+
@Table(
19+
name = "reservation",
20+
indexes = {
21+
@Index(name = "idx_reservation_mentor", columnList = "mentor_id"),
22+
@Index(name = "idx_reservation_mentee", columnList = "mentee_id")
23+
}
24+
)
1725
@Getter
1826
@NoArgsConstructor
1927
public class Reservation extends BaseEntity {
@@ -86,15 +94,10 @@ public void reject(Mentor mentor) {
8694
updateStatus(ReservationStatus.REJECTED);
8795
}
8896

89-
public void cancel(Mentor mentor) {
90-
ensureMentor(mentor);
91-
ensureCanCancel();
92-
ensureNotPast();
93-
updateStatus(ReservationStatus.CANCELED);
94-
}
95-
96-
public void cancel(Mentee mentee) {
97-
ensureMentee(mentee);
97+
public void cancel(Member member) {
98+
if (!mentor.isMember(member) && !mentee.isMember(member) ) {
99+
throw new ServiceException(ReservationErrorCode.FORBIDDEN_NOT_PARTICIPANT);
100+
}
98101
ensureCanCancel();
99102
ensureNotPast();
100103
updateStatus(ReservationStatus.CANCELED);
@@ -114,12 +117,6 @@ private void ensureMentor(Mentor mentor) {
114117
}
115118
}
116119

117-
private void ensureMentee(Mentee mentee) {
118-
if (!isMentee(mentee)) {
119-
throw new ServiceException(ReservationErrorCode.FORBIDDEN_NOT_MENTEE);
120-
}
121-
}
122-
123120
private void ensureCanApprove() {
124121
if(!this.status.canApprove()) {
125122
throw new ServiceException(ReservationErrorCode.CANNOT_APPROVE);

back/src/main/java/com/back/domain/mentoring/reservation/error/ReservationErrorCode.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public enum ReservationErrorCode implements ErrorCode {
2020
// 403
2121
FORBIDDEN_NOT_MENTOR("403-1", "해당 예약에 대한 멘토 권한이 없습니다."),
2222
FORBIDDEN_NOT_MENTEE("403-2", "해당 예약에 대한 멘티 권한이 없습니다."),
23+
FORBIDDEN_NOT_PARTICIPANT("403-3", "해당 예약에 대한 권한이 없습니다"),
24+
RESERVATION_NOT_ACCESSIBLE("403-4", "예약을 찾을 수 없거나 권한이 없습니다"),
2325

2426
// 404
2527
NOT_FOUND_RESERVATION("404-1", "예약이 존재하지 않습니다."),

back/src/main/java/com/back/domain/mentoring/reservation/repository/ReservationRepository.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package com.back.domain.mentoring.reservation.repository;
22

3+
import com.back.domain.member.member.entity.Member;
34
import com.back.domain.mentoring.reservation.constant.ReservationStatus;
45
import com.back.domain.mentoring.reservation.entity.Reservation;
6+
import org.springframework.data.domain.Page;
7+
import org.springframework.data.domain.Pageable;
58
import org.springframework.data.jpa.repository.JpaRepository;
9+
import org.springframework.data.jpa.repository.Query;
10+
import org.springframework.data.repository.query.Param;
611

712
import java.util.List;
813
import java.util.Optional;
@@ -11,6 +16,40 @@ public interface ReservationRepository extends JpaRepository<Reservation, Long>
1116
Optional<Reservation> findTopByOrderByIdDesc();
1217
Optional<Reservation> findByMentorSlotIdAndStatusIn(Long mentorSlotId, List<ReservationStatus> statuses);
1318

19+
@Query("""
20+
SELECT r
21+
FROM Reservation r
22+
WHERE r.id = :reservationId
23+
AND (r.mentee.member = :member
24+
OR r.mentor.member = :member)
25+
""")
26+
Optional<Reservation> findByIdAndMember(
27+
@Param("reservationId") Long reservationId,
28+
@Param("member") Member member
29+
);
30+
31+
@Query("""
32+
SELECT r
33+
FROM Reservation r
34+
WHERE r.mentor.member = :member
35+
ORDER BY r.mentorSlot.startDateTime DESC
36+
""")
37+
Page<Reservation> findAllByMentorMember(
38+
@Param("member") Member member,
39+
Pageable pageable
40+
);
41+
42+
@Query("""
43+
SELECT r
44+
FROM Reservation r
45+
WHERE r.mentee.member = :member
46+
ORDER BY r.mentorSlot.startDateTime DESC
47+
""")
48+
Page<Reservation> findAllByMenteeMember(
49+
@Param("member") Member member,
50+
Pageable pageable
51+
);
52+
1453
boolean existsByMentoringId(Long mentoringId);
1554

1655
/**

0 commit comments

Comments
 (0)