Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.gtable.bookmark.exception;

import com.example.gtable.global.exception.ErrorMessage;

public class BookmarkOwnerMismatchException extends RuntimeException {
public BookmarkOwnerMismatchException() {
super(ErrorMessage.NOT_OWN_BOOKMARK.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.gtable.bookmark.exception;

import com.example.gtable.global.exception.ErrorMessage;

public class DuplicateBookmarkException extends RuntimeException {
public DuplicateBookmarkException() {
super(ErrorMessage.DUPLICATE_BOOKMARK.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
import com.example.gtable.bookmark.dto.BookmarkCreateResponse;
import com.example.gtable.bookmark.dto.BookmarkGetResponse;
import com.example.gtable.bookmark.entity.Bookmark;
import com.example.gtable.bookmark.exception.BookmarkOwnerMismatchException;
import com.example.gtable.bookmark.exception.DuplicateBookmarkException;
import com.example.gtable.bookmark.repository.BookmarkRepository;
import com.example.gtable.global.security.oauth2.dto.CustomOAuth2User;
import com.example.gtable.store.model.Store;
import com.example.gtable.store.repository.StoreRepository;
import com.example.gtable.user.entity.User;
import com.example.gtable.user.exception.MissingUserInfoException;
import com.example.gtable.user.repository.UserRepository;

import jakarta.persistence.EntityNotFoundException;
Expand All @@ -33,7 +36,7 @@ public BookmarkCreateResponse createBookmark(Long storeId, CustomOAuth2User cust
.orElseThrow(() -> new EntityNotFoundException("User not found"));

if (bookmarkRepository.existsByUserAndStore(user, store)) {
throw new IllegalArgumentException("already bookmarked");
throw new DuplicateBookmarkException();
}

Bookmark bookmark = Bookmark.builder()
Expand All @@ -60,7 +63,7 @@ public String deleteBookmark(Long bookmarkId, CustomOAuth2User customOAuth2User)
Bookmark bookmark = bookmarkRepository.findById(bookmarkId)
.orElseThrow(() -> new EntityNotFoundException(bookmarkId + " bookmark not found."));
if (bookmark.getUser().getId() != customOAuth2User.getUserId()) {
throw new IllegalArgumentException("you can only delete your own bookmark");
throw new BookmarkOwnerMismatchException();
}
bookmarkRepository.delete(bookmark);
return "Bookmark ID " + bookmarkId + " deleted.";
Expand All @@ -72,7 +75,7 @@ private static void parameterValidation(Long storeId, CustomOAuth2User customOAu
throw new IllegalArgumentException("storeId must be a positive number");
}
if (customOAuth2User == null || customOAuth2User.getUserId() == null) {
throw new IllegalArgumentException("UserInfo is required");
throw new MissingUserInfoException();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.gtable.global.security.exception;
package com.example.gtable.global.exception;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
Expand All @@ -14,7 +14,13 @@ public enum ErrorMessage {

// token
REFRESH_TOKEN_NOT_FOUND("기존 리프레시 토큰을 찾을 수 없습니다.", "token001"),
DOES_NOT_MATCH_REFRESH_TOKEN("기존 리프레시 토큰이 일치하지 않습니다.", "token002");
DOES_NOT_MATCH_REFRESH_TOKEN("기존 리프레시 토큰이 일치하지 않습니다.", "token002"),

// user
MISSING_USER("사용자 정보가 없습니다.", "user001"),
// bookmark
DUPLICATE_BOOKMARK("이미 북마크한 주점입니다.", "bookmark001"),
NOT_OWN_BOOKMARK("권한이 없습니다.", "bookmark002");

private final String message;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.gtable.global.security.exception;
package com.example.gtable.global.exception;

import java.util.HashMap;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.example.gtable.global.security.exception;
package com.example.gtable.global.exception;

import static com.example.gtable.global.security.exception.ErrorMessage.*;
import static com.example.gtable.global.exception.ErrorMessage.*;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import static org.springframework.http.HttpStatus.*;

import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.context.annotation.Profile;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.validation.FieldError;
Expand All @@ -19,6 +18,13 @@
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

import com.example.gtable.bookmark.exception.BookmarkOwnerMismatchException;
import com.example.gtable.bookmark.exception.DuplicateBookmarkException;
import com.example.gtable.global.security.exception.BusinessException;
import com.example.gtable.global.security.exception.ResourceNotFoundException;
import com.example.gtable.global.security.exception.UnauthorizedException;
import com.example.gtable.user.exception.MissingUserInfoException;

import io.swagger.v3.oas.annotations.Hidden;
import lombok.extern.slf4j.Slf4j;

Expand Down Expand Up @@ -93,6 +99,27 @@ public ErrorResponse handleMultipartException(MultipartException e) {
return new ErrorResponse(e.getMessage(), INVALID_INPUT_VALUE.getCode());
}

@ResponseStatus(value = BAD_REQUEST)
@ExceptionHandler(DuplicateBookmarkException.class)
public ErrorResponse handleDuplicateBookmarkException(DuplicateBookmarkException e) {
log.error("handleDuplicateBookmarkException", e);
return new ErrorResponse(e.getMessage(), ErrorMessage.DUPLICATE_BOOKMARK.getCode());
}

@ResponseStatus(value = BAD_REQUEST)
@ExceptionHandler(BookmarkOwnerMismatchException.class)
public ErrorResponse bookmarkOwnerMismatchException(BookmarkOwnerMismatchException e) {
log.error("bookmarkOwnerMismatchException", e);
return new ErrorResponse(e.getMessage(), NOT_OWN_BOOKMARK.getCode());
}

@ResponseStatus(value = NOT_FOUND)
@ExceptionHandler(MissingUserInfoException.class)
public ErrorResponse missingUserInfoException(MissingUserInfoException e) {
log.error("missingUserInfoException", e);
return new ErrorResponse(e.getMessage(), MISSING_USER.getCode());
}


private static Map<String, String> getErrors(MethodArgumentNotValidException e) {
return e.getBindingResult()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.example.gtable.global.security.exception;

import com.example.gtable.global.exception.ErrorMessage;

public abstract class BusinessException extends RuntimeException {
private final ErrorMessage errorMessage;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.example.gtable.global.security.exception;

import com.example.gtable.global.exception.ErrorMessage;

public class RefreshTokenNotFoundException extends ResourceNotFoundException {

public RefreshTokenNotFoundException() {
super(ErrorMessage.REFRESH_TOKEN_NOT_FOUND);
super(ErrorMessage.valueOf(ErrorMessage.REFRESH_TOKEN_NOT_FOUND.getMessage()));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.example.gtable.global.security.exception;

import com.example.gtable.global.exception.ErrorMessage;

public abstract class ResourceNotFoundException extends RuntimeException {
private final ErrorMessage errorMessage;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.example.gtable.global.security.exception;

import com.example.gtable.global.exception.ErrorMessage;

public class TokenBadRequestException extends BusinessException {
public TokenBadRequestException() {
super(ErrorMessage.DOES_NOT_MATCH_REFRESH_TOKEN);
super(ErrorMessage.valueOf(ErrorMessage.DOES_NOT_MATCH_REFRESH_TOKEN.getMessage()));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.example.gtable.global.security.exception;

import com.example.gtable.global.exception.ErrorMessage;

public class UnauthorizedException extends RuntimeException {
private final ErrorMessage errorMessage;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.example.gtable.reservation.controller;


import java.util.List;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import com.example.gtable.global.api.ApiUtils;
import com.example.gtable.global.security.oauth2.dto.CustomOAuth2User;
import com.example.gtable.reservation.dto.ReservationCreateRequestDto;
import com.example.gtable.reservation.dto.ReservationCreateResponseDto;
import com.example.gtable.reservation.dto.ReservationGetResponseDto;
import com.example.gtable.reservation.service.ReservationService;
@Tag(name = "Reservation API", description = "예약 API")
@RestController
@RequestMapping("/reservations")
@RequiredArgsConstructor
public class ReservationController {

private final ReservationService reservationService;

@PostMapping("/create/{storeId}")
@Operation(summary = "예약 생성", description = "특정 주점에 대한 예약하기 생성")
@ApiResponse(responseCode = "201", description = "예약 생성")
public ResponseEntity<?> create(
@PathVariable Long storeId,
@AuthenticationPrincipal CustomOAuth2User customOAuth2User,
@RequestBody ReservationCreateRequestDto requestDto) {
ReservationCreateResponseDto response = reservationService.create(storeId, customOAuth2User, requestDto);
return ResponseEntity
.status(HttpStatus.CREATED)
.body(
ApiUtils.success(
response
)
);
}

@GetMapping("/admin/{storeId}")
@Operation(summary = "주점별 예약리스트 조회", description = "특정 주점에 대한 예약리스트 조회")
@ApiResponse(responseCode = "200", description = "예약리스트 조회")
public ResponseEntity<?> getReservationListByStoreId(@PathVariable Long storeId) {
List<ReservationGetResponseDto> response = reservationService.getReservationListByStoreId(storeId);
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
response
)
);
}

// @PatchMapping("/{id}/status")
// public ReservationDto.Response updateStatus(
// @PathVariable Long id,
// @RequestParam Reservation.Status status
// ) {
// return reservationService.updateStatus(id, status);
// }
//
// @DeleteMapping("/{id}")
// public void delete(@PathVariable Long id) {
// reservationService.delete(id);
// }


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.example.gtable.reservation.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ReservationCreateRequestDto {
private Integer partySize;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.gtable.reservation.dto;

import lombok.Builder;
import lombok.Getter;
import java.time.LocalDateTime;

@Getter
@Builder
public class ReservationCreateResponseDto {
private Long id;
private Long storeId;
private Long userId;
private LocalDateTime requestedAt;
private String status;
private Integer partySize;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.example.gtable.reservation.dto;

import java.time.LocalDateTime;

import com.example.gtable.bookmark.dto.BookmarkGetResponse;
import com.example.gtable.bookmark.entity.Bookmark;
import com.example.gtable.reservation.entity.Reservation;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ReservationGetResponseDto {
private Long id;
private Long storeId;
private String userName;
private LocalDateTime requestedAt;
private String status;
private Integer partySize;

public static ReservationGetResponseDto fromEntity(Reservation reservation) {
return ReservationGetResponseDto.builder()
.id(reservation.getId())
.storeId(reservation.getStore().getStoreId())
.userName(reservation.getUser().getNickname())
.requestedAt(reservation.getRequestedAt())
.status(reservation.getStatus().name())
.partySize(reservation.getPartySize())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.example.gtable.reservation.entity;
import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;

import com.example.gtable.store.model.Store;
import com.example.gtable.user.entity.User;

@Entity
@Table(name = "waiting_requests")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public class Reservation {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "store_id")
private Store store;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id")
private User user;

@Column(name = "requested_at", nullable = false)
private LocalDateTime requestedAt;

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private ReservationStatus status;

@Column(name = "party_size", nullable = false)
private Integer partySize;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.example.gtable.reservation.entity;

public enum ReservationStatus {
WAITING,CALLING, CONFIRMED, CANCELLED
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.gtable.reservation.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.gtable.reservation.entity.Reservation;

public interface ReservationRepository extends JpaRepository<Reservation, Long> {
List<Reservation> findAllByStore_StoreId(Long storeId);
}
Loading