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
@@ -1,24 +1,29 @@
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 org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
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 com.example.gtable.global.api.ApiUtils;
import com.example.gtable.global.security.oauth2.dto.CustomOAuth2User;
import com.example.gtable.reservation.dto.CallGetResponseDto;
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.dto.ReservationStatusSummaryDto;
import com.example.gtable.reservation.dto.ReservationStatusUpdateRequestDto;
import com.example.gtable.reservation.service.ReservationService;

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;
@Tag(name = "Reservation API", description = "예약 API")
@RestController
@RequestMapping("/reservations")
Expand Down Expand Up @@ -48,7 +53,7 @@ public ResponseEntity<?> create(
@Operation(summary = "주점별 예약리스트 조회", description = "특정 주점에 대한 예약리스트 조회")
@ApiResponse(responseCode = "200", description = "예약리스트 조회")
public ResponseEntity<?> getReservationListByStoreId(@PathVariable Long storeId) {
List<ReservationGetResponseDto> response = reservationService.getReservationListByStoreId(storeId);
ReservationStatusSummaryDto response = reservationService.getReservationListByStoreId(storeId);
return ResponseEntity
.status(HttpStatus.OK)
.body(
Expand All @@ -58,18 +63,20 @@ public ResponseEntity<?> getReservationListByStoreId(@PathVariable Long storeId)
);
}

// @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);
// }
@PatchMapping("/admin/updates/{reservationId}")
@Operation(summary = "예약팀 상태 변경", description = "특정 예약에 대한 상태 변경(예약중->호출중,호출중->입장완료,취소)")
@ApiResponse(responseCode = "200", description = "예약팀 상태 변경")
public ResponseEntity<?> updateReservationStatus(@PathVariable Long reservationId,@RequestBody
ReservationStatusUpdateRequestDto requestDto) {
CallGetResponseDto response = reservationService.updateReservationStatus(reservationId,requestDto);
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
response
)
);
}


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

import java.time.LocalDateTime;

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

import lombok.Builder;
import lombok.Getter;

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

public static CallGetResponseDto fromEntity(Reservation reservation) {
return CallGetResponseDto.builder()
.id(reservation.getId())
.storeId(reservation.getStore().getStoreId())
.userName(reservation.getUser().getNickname())
.requestedAt(reservation.getRequestedAt())
.status(reservation.getStatus().name())
.partySize(reservation.getPartySize())
.build();
}
Comment on lines +20 to +29
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

fromEntity 메서드에 null 안전성 검증을 추가해주세요.

DTO 변환 로직이 깔끔하게 구현되었습니다. 다만 연관 엔티티들이 null일 가능성에 대비한 안전장치를 추가하면 더욱 안정적인 코드가 될 것입니다.

 public static CallGetResponseDto fromEntity(Reservation reservation) {
+    if (reservation == null) {
+        throw new IllegalArgumentException("예약 정보는 null일 수 없습니다.");
+    }
+    if (reservation.getStore() == null || reservation.getUser() == null) {
+        throw new IllegalStateException("예약의 매장 또는 사용자 정보가 누락되었습니다.");
+    }
+    
     return CallGetResponseDto.builder()
         .id(reservation.getId())
         .storeId(reservation.getStore().getStoreId())
         .userName(reservation.getUser().getNickname())
         .requestedAt(reservation.getRequestedAt())
         .status(reservation.getStatus().name())
         .partySize(reservation.getPartySize())
         .build();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static CallGetResponseDto fromEntity(Reservation reservation) {
return CallGetResponseDto.builder()
.id(reservation.getId())
.storeId(reservation.getStore().getStoreId())
.userName(reservation.getUser().getNickname())
.requestedAt(reservation.getRequestedAt())
.status(reservation.getStatus().name())
.partySize(reservation.getPartySize())
.build();
}
public static CallGetResponseDto fromEntity(Reservation reservation) {
if (reservation == null) {
throw new IllegalArgumentException("예약 정보는 null일 수 없습니다.");
}
if (reservation.getStore() == null || reservation.getUser() == null) {
throw new IllegalStateException("예약의 매장 또는 사용자 정보가 누락되었습니다.");
}
return CallGetResponseDto.builder()
.id(reservation.getId())
.storeId(reservation.getStore().getStoreId())
.userName(reservation.getUser().getNickname())
.requestedAt(reservation.getRequestedAt())
.status(reservation.getStatus().name())
.partySize(reservation.getPartySize())
.build();
}
🤖 Prompt for AI Agents
In src/main/java/com/example/gtable/reservation/dto/CallGetResponseDto.java
around lines 20 to 29, the fromEntity method lacks null safety checks for
associated entities like store and user. To fix this, add null checks before
accessing properties of reservation.getStore() and reservation.getUser() to
avoid NullPointerExceptions. Use conditional checks or Optional to safely
retrieve values or provide default values when these related entities are null.

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

import java.util.List;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@AllArgsConstructor
public class ReservationStatusSummaryDto {
private int waitingCount;
private int confirmedCount;
private int cancelledCount;
private int callingCount;
private List<ReservationGetResponseDto> reservationList;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.gtable.reservation.dto;

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

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ReservationStatusUpdateRequestDto {
private ReservationStatus status;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ public class Reservation {
@Column(name = "party_size", nullable = false)
private Integer partySize;

public void updateStatus(ReservationStatus status) {
this.status = status;
}
Comment on lines +39 to +41
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

상태 업데이트 메서드에 입력값 검증을 추가해주세요.

메서드가 깔끔하게 구현되었지만, null 값에 대한 검증이 없어서 안전성을 높이기 위해 개선이 필요합니다.

 public void updateStatus(ReservationStatus status) {
+    if (status == null) {
+        throw new IllegalArgumentException("예약 상태는 null일 수 없습니다.");
+    }
     this.status = status;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void updateStatus(ReservationStatus status) {
this.status = status;
}
public void updateStatus(ReservationStatus status) {
if (status == null) {
throw new IllegalArgumentException("예약 상태는 null일 수 없습니다.");
}
this.status = status;
}
🤖 Prompt for AI Agents
In src/main/java/com/example/gtable/reservation/entity/Reservation.java around
lines 39 to 41, the updateStatus method lacks validation for null input, which
can lead to unsafe state changes. Add a null check at the start of the method to
verify that the status parameter is not null, and handle the null case
appropriately, such as throwing an IllegalArgumentException or ignoring the
update, to ensure method robustness.


}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
import com.example.gtable.reservation.entity.Reservation;

public interface ReservationRepository extends JpaRepository<Reservation, Long> {
List<Reservation> findAllByStore_StoreId(Long storeId);
List<Reservation> findAllByStore_StoreIdOrderByRequestedAtAsc(Long storeId);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.example.gtable.reservation.service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.gtable.global.security.oauth2.dto.CustomOAuth2User;
import com.example.gtable.reservation.dto.CallGetResponseDto;
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.dto.ReservationStatusSummaryDto;
import com.example.gtable.reservation.dto.ReservationStatusUpdateRequestDto;
import com.example.gtable.reservation.entity.Reservation;
import com.example.gtable.reservation.entity.ReservationStatus;
import com.example.gtable.reservation.repository.ReservationRepository;
Expand Down Expand Up @@ -55,14 +59,39 @@ public ReservationCreateResponseDto create(Long storeId, CustomOAuth2User custom
.build();
}
@Transactional(readOnly = true)
public List<ReservationGetResponseDto> getReservationListByStoreId(Long storeId) {
List<Reservation> reservations = reservationRepository.findAllByStore_StoreId(storeId);
public ReservationStatusSummaryDto getReservationListByStoreId(Long storeId) {
List<Reservation> reservations = reservationRepository.findAllByStore_StoreIdOrderByRequestedAtAsc(storeId);

return reservations.stream()
.map(ReservationGetResponseDto::fromEntity)
.toList();
// 상태별 카운트 집계
int waitingCount = 0;
int confirmedCount = 0;
int cancelledCount = 0;
int callingCount = 0;
List<ReservationGetResponseDto> reservationDtoList = new ArrayList<>();
for (Reservation r : reservations) {
if (r.getStatus() == ReservationStatus.WAITING) waitingCount++;
if (r.getStatus() == ReservationStatus.CONFIRMED) confirmedCount++;
if (r.getStatus() == ReservationStatus.CANCELLED) cancelledCount++;
if (r.getStatus() == ReservationStatus.CALLING) callingCount++;
reservationDtoList.add(ReservationGetResponseDto.fromEntity(r));
}

return ReservationStatusSummaryDto.builder()
.waitingCount(waitingCount)
.confirmedCount(confirmedCount)
.cancelledCount(cancelledCount)
.callingCount(callingCount)
.reservationList(reservationDtoList)
.build();
}
@Transactional
public CallGetResponseDto updateReservationStatus(Long reservationId, ReservationStatusUpdateRequestDto requestDto) {
Reservation reservation = reservationRepository.findById(reservationId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 reservation"));
reservation.updateStatus(requestDto.getStatus());
return CallGetResponseDto.fromEntity(reservation);
}


// 나머지 메서드도 동일하게 store/user 접근 시 getId() 활용
}

Loading