Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3 - 4단계 방탈출 예약 대기] 카피(김상혁) 미션 제출합니다. #107

Merged
merged 47 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
9d1798e
fix: 불필요 ddl 컬럼 삭제
tkdgur0906 May 20, 2024
f5047da
refactor: jpa 자동 ddl 생성 none 설정
tkdgur0906 May 20, 2024
ae81820
feat: 3단계 클라이언트 코드 추가
tkdgur0906 May 20, 2024
f2b0572
chore: jpa ddl auto를 validate로 변경
tkdgur0906 May 20, 2024
a14d4ed
refactor: 예약 여부 객체 이름 명확히 변경
tkdgur0906 May 20, 2024
fa12a9b
feat: 예약 엔티티에 예약 상태 필드 추가 및 예약 생성 시 예약,대기 여부 받도록 변경
tkdgur0906 May 20, 2024
711f902
feat: 예약 대기 요청 api 구현
tkdgur0906 May 21, 2024
f3921df
feat: 예약 상태 출력 시 예약, 예약대기를 구분하여 출력하는 기능 구현
tkdgur0906 May 21, 2024
c34818a
feat: 이미 요청한 예약, 예약대기가 존재하는지 검증하는 기능 구현
tkdgur0906 May 21, 2024
105b664
feat: 예약페이지 시간 출력 시 시,분만 출력되도록 기능 추가
tkdgur0906 May 21, 2024
61eff92
feat: 기본 예약 대기 데이터 추가
tkdgur0906 May 21, 2024
4ffdea9
feat: 예약 대기 취소 api 구현
tkdgur0906 May 21, 2024
f537c88
refactor: 예약 대기 api 엔드포인트 waitings로 변경
tkdgur0906 May 21, 2024
904e2b5
refactor: 예약 삭제 api 메서드 명 올바르게 수정
tkdgur0906 May 21, 2024
b8efcd6
feat: 모든 엔티티 생성시간 저장하도록 컬럼 추가
tkdgur0906 May 21, 2024
300be37
refactor: 작성 쿼리 가독성있게 변경
tkdgur0906 May 21, 2024
b7cf143
feat: 내 예약 목록의 예약 대기 상태에 몇번째 대기인지 포함하는 기능 구현
tkdgur0906 May 22, 2024
aee0764
feat: 4단계 예약 대기 관리 기능 클라이언트 코드 추가
tkdgur0906 May 22, 2024
c68f262
feat: 예약 대기 관리 페이지 렌더링 기능 구현
tkdgur0906 May 22, 2024
94255cb
refactor: 예약대기 엔드포인트 waiting 으로 변경
tkdgur0906 May 22, 2024
8af3ed5
feat: 예약 대기 목록 조회하는 api 구현
tkdgur0906 May 22, 2024
2a92b00
feat: 어드민 예약 대기 조회 페이지 네비게이션 바 추가
tkdgur0906 May 22, 2024
f5234a0
feat: 예약 대기 취소 api 구현
tkdgur0906 May 22, 2024
8d5500d
feat: 예약 취소 발생시 예약 대기 자동으로 승인하는 기능 구현
tkdgur0906 May 22, 2024
2a06d47
style: 전체 코드 가독성 있게 줄바꿈 적용
tkdgur0906 May 23, 2024
71d23b4
refactor: api 엔드포인트 맨앞에 /api를 붙여 구분하도록 변경
tkdgur0906 May 23, 2024
4488375
feat: 예약 삭제를 관리자만 가능하도록 기능 추가
tkdgur0906 May 23, 2024
952c1a6
feat: 예약 시간 추가, 삭제를 관리자만 가능하도록 기능 추가
tkdgur0906 May 23, 2024
dd60fc5
feat: 테마 추가, 삭제를 관리자만 가능하도록 기능 추가
tkdgur0906 May 23, 2024
8f0f7bd
test: 실패하는 테스트 수정
tkdgur0906 May 23, 2024
72340aa
feat: 예약 대기 삭제 시 본인, 관리자만 삭제할 수 있도록 기능 추가
tkdgur0906 May 23, 2024
e6922d2
refactor: 특정 날짜, 테마의 시간 별 예약 여부를 찾는 메서드 이름 명확히 변경
tkdgur0906 May 24, 2024
90b837e
refactor: 예약 상태 변경 메서드 파라미터 받아서 적용하도록 변경
tkdgur0906 May 24, 2024
e30e447
refactor: enum 비교 ==로 하도록 변경
tkdgur0906 May 24, 2024
91161ad
refactor: User를 Member로 명명 통일
tkdgur0906 May 24, 2024
a1df0cf
refactor: 서비스 CRD로 분류하지 않고 하나로 통일
tkdgur0906 May 26, 2024
a439eec
refactor: 예약, 대기 요청 여부을 클라이언트에서 request로 넘기도록 변경하여 하나의 예약 api에서 처리하도록 변경
tkdgur0906 May 26, 2024
3e8fe2c
feat: 사용자가 예약 삭제 시 예약 대기만 삭제할 수 있도록 검증
tkdgur0906 May 26, 2024
aeb44de
refactor: 사용자 예약 대기 취소 api 엔드포인트 reservations으로 변경
tkdgur0906 May 26, 2024
26b29a6
fix: 잘못된 테마 삭제 엔드포인트 수정
tkdgur0906 May 26, 2024
e3498d6
refactor: 모든 예약, 예약 대기 삭제 api를 예약 삭제 api 하나로 통일
tkdgur0906 May 26, 2024
0ea3648
refactor: 관리자 예약 목록 리스트 조회 api 엔드포인트 리소스를 예약으로 변경
tkdgur0906 May 26, 2024
fa306e2
refactor: 중복되는 api RequestMapping으로 공통 처리
tkdgur0906 May 26, 2024
f4e466e
refactor: 예약 대기 목록 조회 메서드 대신 예약 상태에 따라 조회할 수 있도록 변경
tkdgur0906 May 26, 2024
4ce74c0
refactor: 예약 여부 반환하는 메서드 equals 대신 contains 사용
tkdgur0906 May 26, 2024
17c2c6a
style: sql 들여쓰기
tkdgur0906 May 26, 2024
15083f8
refactor: reservation 버튼 클릭시 홈으로 가지 않고 예약 페이지로 이동하도록 변경
tkdgur0906 May 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/roomescape/RoomescapeApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class RoomescapeApplication {
public static void main(String[] args) {
SpringApplication.run(RoomescapeApplication.class, args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public class AdminAuthHandlerInterceptor implements HandlerInterceptor {
private final AuthService authService;
private final TokenProvider tokenProvider;

public AdminAuthHandlerInterceptor(AuthService authService, TokenProvider tokenProvider) {
public AdminAuthHandlerInterceptor(AuthService authService,
TokenProvider tokenProvider) {
this.authService = authService;
this.tokenProvider = tokenProvider;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ public class AuthenticatedMemberArgumentResolver implements HandlerMethodArgumen
private final AuthService authService;
private final TokenProvider tokenProvider;

public AuthenticatedMemberArgumentResolver(AuthService authService, TokenProvider tokenProvider) {
public AuthenticatedMemberArgumentResolver(AuthService authService,
TokenProvider tokenProvider) {
this.authService = authService;
this.tokenProvider = tokenProvider;
}

@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(AuthenticatedMember.class)
&& Member.class.isAssignableFrom(parameter.getParameterType());
&& Member.class.isAssignableFrom(parameter.getParameterType());
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/roomescape/config/AuthWebConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers)

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(adminAuthHandlerInterceptor).addPathPatterns("/admin/**");
registry.addInterceptor(adminAuthHandlerInterceptor).addPathPatterns("/admin/**", "/api/admin/**");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import roomescape.auth.AuthenticatedMember;
import roomescape.domain.Member;
import roomescape.service.auth.AuthService;
import roomescape.service.dto.request.LoginRequest;
import roomescape.service.dto.response.MemberIdAndNameResponse;

@RequestMapping("/api")
@RestController
public class AuthApiController {

Expand All @@ -29,7 +31,9 @@ public ResponseEntity<MemberIdAndNameResponse> getMemberLoginInfo(@Authenticated
}

@PostMapping("/login")
public ResponseEntity<Void> login(@RequestBody @Valid LoginRequest request, HttpServletResponse response) {
public ResponseEntity<Void> login(@RequestBody @Valid
LoginRequest request,
HttpServletResponse response) {
String accessToken = authService.login(request);
Cookie cookie = new Cookie("token", accessToken);
cookie.setHttpOnly(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ public MemberApiController(MemberService memberService) {
this.memberService = memberService;
}

@PostMapping("/members")
public ResponseEntity<MemberIdAndNameResponse> signup(@RequestBody @Valid SignupRequest request) {
@PostMapping("/api/members")
public ResponseEntity<MemberIdAndNameResponse> signup(@RequestBody @Valid
SignupRequest request) {
Comment on lines +25 to +26

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public ResponseEntity<MemberIdAndNameResponse> signup(@RequestBody @Valid
SignupRequest request) {
public ResponseEntity<MemberIdAndNameResponse> signup(
@RequestBody @Valid SignupRequest request
) {

파라미터는 어노테이션을 개행하면 어디에 적용하는지 쉽게 안보여서 한줄로 처리할 수 있도록 해주는게 좋을것 같아요!

Member member = memberService.signUp(request);
return ResponseEntity.created(URI.create("/members/" + member.getId()))
return ResponseEntity.created(URI.create("/api/members/" + member.getId()))
.body(new MemberIdAndNameResponse(member.getId(), member.getName()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,35 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import roomescape.auth.AuthenticatedMember;
import roomescape.domain.Member;
import roomescape.domain.Reservation;
import roomescape.domain.ReservationStatus;
import roomescape.domain.ReservationWaitingWithRank;
import roomescape.service.dto.request.ReservationSaveRequest;
import roomescape.service.dto.response.MemberReservationResponse;
import roomescape.service.dto.response.ReservationResponse;
import roomescape.service.dto.response.UserReservationResponse;
import roomescape.service.reservation.ReservationCreateService;
import roomescape.service.reservation.ReservationDeleteService;
import roomescape.service.reservation.ReservationFindService;
import roomescape.service.reservation.ReservationService;

import java.net.URI;
import java.util.List;

@Validated
@RequestMapping("/api")
@RestController
public class ReservationApiController {

private final ReservationCreateService reservationCreateService;
private final ReservationFindService reservationFindService;
private final ReservationDeleteService reservationDeleteService;
private final ReservationService reservationService;

public ReservationApiController(ReservationCreateService reservationCreateService,
ReservationFindService reservationFindService,
ReservationDeleteService reservationDeleteService) {
this.reservationCreateService = reservationCreateService;
this.reservationFindService = reservationFindService;
this.reservationDeleteService = reservationDeleteService;
public ReservationApiController(ReservationService reservationService) {
this.reservationService = reservationService;
}

@GetMapping("/reservations")
public ResponseEntity<List<ReservationResponse>> getReservations() {
List<Reservation> reservations = reservationFindService.findReservations();
List<Reservation> reservations = reservationService.findReservations();
return ResponseEntity.ok(
reservations.stream()
.map(ReservationResponse::new)
Expand All @@ -50,27 +46,34 @@ public ResponseEntity<List<ReservationResponse>> getReservations() {
}

@GetMapping("/reservations-mine")
public ResponseEntity<List<UserReservationResponse>> getUserReservations(@AuthenticatedMember Member member) {
List<Reservation> userReservations = reservationFindService.findUserReservations(member.getId());
public ResponseEntity<List<MemberReservationResponse>> getMemberReservations(@AuthenticatedMember Member member) {
List<ReservationWaitingWithRank> reservationWaitingWithRanks =
reservationService.findMemberReservations(member.getId());
return ResponseEntity.ok(
userReservations.stream()
.map(UserReservationResponse::new)
reservationWaitingWithRanks.stream()
.map(MemberReservationResponse::new)
.toList()
);
}

@PostMapping("/reservations")
public ResponseEntity<ReservationResponse> addReservationByUser(@RequestBody @Valid ReservationSaveRequest request,
@AuthenticatedMember Member member) {
Reservation newReservation = reservationCreateService.createReservation(request, member);
return ResponseEntity.created(URI.create("/reservations/" + newReservation.getId()))
public ResponseEntity<ReservationResponse> addReservationByMember(@RequestBody @Valid
ReservationSaveRequest request,
@AuthenticatedMember Member member) {
Reservation newReservation = reservationService.createReservation(
request,
member
);
return ResponseEntity.created(URI.create("/api/reservations/" + newReservation.getId()))
.body(new ReservationResponse(newReservation));
}

@DeleteMapping("/reservations/{id}")
public ResponseEntity<Void> deleteReservation(@PathVariable
@Positive(message = "1 이상의 값만 입력해주세요.") long id) {
reservationDeleteService.deleteReservation(id);
public ResponseEntity<Void> deleteWaiting(@AuthenticatedMember Member member,
@PathVariable
@Positive(message = "1 이상의 값만 입력해주세요.")
long id) {
reservationService.deleteReservation(id, member);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -1,84 +1,57 @@
package roomescape.controller.api;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Positive;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import roomescape.domain.ReservationStatus;
import roomescape.domain.BookingStatus;
import roomescape.domain.ReservationTime;
import roomescape.service.dto.request.ReservationTimeSaveRequest;
import roomescape.service.dto.response.ReservationStatusResponse;
import roomescape.service.dto.response.BookingStatusResponse;
import roomescape.service.dto.response.ReservationTimeResponse;
import roomescape.service.reservationtime.ReservationTimeCreateService;
import roomescape.service.reservationtime.ReservationTimeDeleteService;
import roomescape.service.reservationtime.ReservationTimeFindService;
import roomescape.service.reservationtime.ReservationTimeService;

import java.net.URI;
import java.time.LocalDate;
import java.util.List;

@Validated
@RequestMapping("/api/times")
@RestController
public class ReservationTimeApiController {

private final ReservationTimeCreateService reservationTimeCreateService;
private final ReservationTimeFindService reservationTimeFindService;
private final ReservationTimeDeleteService reservationTimeDeleteService;
private final ReservationTimeService reservationTimeService;

public ReservationTimeApiController(ReservationTimeCreateService reservationTimeCreateService,
ReservationTimeFindService reservationTimeFindService,
ReservationTimeDeleteService reservationTimeDeleteService) {
this.reservationTimeCreateService = reservationTimeCreateService;
this.reservationTimeFindService = reservationTimeFindService;
this.reservationTimeDeleteService = reservationTimeDeleteService;
public ReservationTimeApiController(ReservationTimeService reservationTimeService) {
this.reservationTimeService = reservationTimeService;
}

@GetMapping("/times")
@GetMapping
public ResponseEntity<List<ReservationTimeResponse>> getReservationTimes() {
List<ReservationTime> reservationTimes = reservationTimeFindService.findReservationTimes();
List<ReservationTime> reservationTimes = reservationTimeService.findReservationTimes();
return ResponseEntity.ok(
reservationTimes.stream()
.map(ReservationTimeResponse::new)
.toList()
);
}

@GetMapping("/times/available")
public ResponseEntity<List<ReservationStatusResponse>> getReservationTimesIsBooked(
@RequestParam LocalDate date,
@RequestParam @Positive(message = "1 이상의 값만 입력해주세요.") long themeId) {
ReservationStatus reservationStatus = reservationTimeFindService.findIsBooked(date, themeId);
@GetMapping("/available")
public ResponseEntity<List<BookingStatusResponse>> getReservationTimesIsBooked(@RequestParam LocalDate date,
@RequestParam
@Positive(message = "1 이상의 값만 입력해주세요.")
long themeId) {
BookingStatus bookingStatus = reservationTimeService.findTimeSlotsBookingStatus(date, themeId);
return ResponseEntity.ok(
reservationStatus.getReservationStatus()
bookingStatus.getReservationStatus()
.entrySet()
.stream()
.map(status -> new ReservationStatusResponse(
.map(status -> new BookingStatusResponse(
status.getKey(),
status.getValue()
)
).toList()
);
}

@PostMapping("/times")
public ResponseEntity<ReservationTimeResponse> addReservationTime(
@RequestBody @Valid ReservationTimeSaveRequest request) {
ReservationTime reservationTime = reservationTimeCreateService.createReservationTime(request);
return ResponseEntity.created(URI.create("times/" + reservationTime.getId()))
.body(new ReservationTimeResponse(reservationTime));
}

@DeleteMapping("/times/{id}")
public ResponseEntity<Void> deleteReservationTime(@PathVariable
@Positive(message = "1 이상의 값만 입력해주세요.") long id) {
reservationTimeDeleteService.deleteReservationTime(id);
return ResponseEntity.noContent().build();
}
}
51 changes: 12 additions & 39 deletions src/main/java/roomescape/controller/api/ThemeApiController.java
Original file line number Diff line number Diff line change
@@ -1,71 +1,44 @@
package roomescape.controller.api;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Positive;
import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import roomescape.domain.Theme;
import roomescape.service.dto.request.ThemeSaveRequest;
import roomescape.service.dto.response.ThemeResponse;
import roomescape.service.theme.ThemeCreateService;
import roomescape.service.theme.ThemeDeleteService;
import roomescape.service.theme.ThemeFindService;
import roomescape.service.theme.ThemeService;

import java.util.List;

@Validated
@RequestMapping("/api/themes")
@RestController
public class ThemeApiController {

private final ThemeCreateService themeCreateService;
private final ThemeFindService themeFindService;
private final ThemeDeleteService themeDeleteService;
private final ThemeService themeService;

public ThemeApiController(ThemeCreateService themeCreateService,
ThemeFindService themeFindService,
ThemeDeleteService themeDeleteService) {
this.themeCreateService = themeCreateService;
this.themeFindService = themeFindService;
this.themeDeleteService = themeDeleteService;
public ThemeApiController(ThemeService themeService) {
this.themeService = themeService;
}

@GetMapping("/themes")
@GetMapping
public ResponseEntity<List<ThemeResponse>> getThemes() {
List<Theme> themes = themeFindService.findThemes();
List<Theme> themes = themeService.findThemes();
return ResponseEntity.ok(
themes.stream()
.map(ThemeResponse::new)
.toList()
);
}

@GetMapping("/themes/ranks")
@GetMapping("/ranks")
public ResponseEntity<List<ThemeResponse>> getThemeRanks() {
List<Theme> themes = themeFindService.findThemeRanks();
List<Theme> themes = themeService.findThemeRanks();
return ResponseEntity.ok(
themes.stream()
.map(ThemeResponse::new)
.toList()
);
}

@PostMapping("/themes")
public ResponseEntity<ThemeResponse> addTheme(@RequestBody @Valid ThemeSaveRequest request) {
Theme theme = themeCreateService.createTheme(request);
return ResponseEntity.created(URI.create("/themes/" + theme.getId()))
.body(new ThemeResponse(theme));
}

@DeleteMapping("/themes/{id}")
public ResponseEntity<Void> deleteTheme(@PathVariable
@Positive(message = "1 이상의 값만 입력해주세요.") long id) {
themeDeleteService.deleteTheme(id);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public AdminMemberApiController(MemberService memberService) {
this.memberService = memberService;
}

@GetMapping("/admin/members")
@GetMapping("/api/admin/members")
public ResponseEntity<List<MemberIdAndNameResponse>> getMembers() {
List<Member> members = memberService.findMembers();
return ResponseEntity.ok(
Expand Down
Loading