Skip to content

Conversation

@HyemIin
Copy link
Member

@HyemIin HyemIin commented Jun 20, 2025

작업 요약

  • 세션 기반 사용자별 주문 조회 로직 구현
  • price 타입 Integer로 변경

Issue Link

#30

문제점 및 어려움

  • 정확히는, 팀 단위로 주문을 구분하는 것이 아닌, 주문한 기기 단위로 구분

해결 방안

  • 현재는 이것이 최선
  • 정확히 팀단위로 구분하려면 매 주문마다 qr코드를 따로 출력해야함

Reference

Summary by CodeRabbit

  • 신규 기능

    • 세션 기반 주문 생성 및 주문 항목 조회 기능이 추가되었습니다.
    • 주문 항목 목록을 반환하는 새로운 응답 형식이 도입되었습니다.
  • 기능 개선

    • 메뉴 가격 관련 필드의 자료형이 문자열에서 정수형으로 변경되어, 가격 입력 및 표시가 더욱 명확해졌습니다.
  • 버그 수정

    • 주문 생성 API 설명이 올바르게 수정되었습니다.

- 세션 기반 사용자별 주문 조회 로직 구현
- price 타입 Integer로 변경
@HyemIin HyemIin self-assigned this Jun 20, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 20, 2025

Walkthrough

이번 변경에서는 메뉴 및 주문 관련 DTO와 엔티티의 가격 타입을 String에서 Integer로 일괄 변경하였고, 주문 생성 및 조회 시 세션 기반 처리를 도입하였습니다. 주문 아이템 목록을 반환하는 신규 DTO와 API 엔드포인트가 추가되었으며, 주문 엔티티에 세션 ID와 주문 아이템 리스트 필드가 신설되었습니다.

Changes

파일(들) 변경 요약
.../menu/dto/MenuCreateRequest.java,
.../menu/dto/MenuCreateResponse.java,
.../menu/dto/MenuReadDto.java,
.../menu/model/Menu.java
메뉴 관련 DTO 및 엔티티의 price 필드 타입을 String에서 Integer로 변경
.../order/controller/OrderController.java 주문 생성 시 세션 기반 처리 추가, 주문 아이템 목록 조회용 GET 엔드포인트 신설
.../order/entity/UserOrder.java orderItems(1:N) 필드 및 sessionId 필드 추가, 빌더 어노테이션 변경
.../order/repository/OrderRepository.java findByStore_StoreIdAndTableIdAndSessionId 메서드 추가
.../order/service/OrderService.java createOrdersessionId 파라미터 추가, 주문 아이템 목록 반환 메서드 신설
.../orderitem/dto/OrderItemListGetResponseDto.java 주문 아이템 목록 응답용 DTO 신설 및 fromEntity 팩토리 메서드 구현

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant OrderController
    participant OrderService
    participant OrderRepository
    participant UserOrder
    participant OrderItem

    Client->>OrderController: POST /orders/{storeId}/{tableId} (with session)
    OrderController->>OrderService: createOrder(storeId, tableId, requestDto, sessionId)
    OrderService->>UserOrder: 생성 (sessionId 포함)
    OrderService-->>OrderController: OrderCreateResponseDto
    OrderController-->>Client: Response

    Client->>OrderController: GET /orders/items/{storeId}/{tableId} (with session)
    OrderController->>OrderService: getOrderItems(storeId, tableId, sessionId)
    OrderService->>OrderRepository: findByStore_StoreIdAndTableIdAndSessionId
    OrderRepository-->>OrderService: List<UserOrder>
    OrderService->>OrderItem: 주문별 OrderItem 추출
    OrderService-->>OrderController: List<OrderItemListGetResponseDto>
    OrderController-->>Client: ResponseEntity<List<...>>
Loading

Possibly related PRs

  • feat(order): order create #47: 기존 주문 생성 플로우를 도입한 PR로, 이번 PR은 세션 처리 및 주문 아이템 조회 등 해당 기능을 확장 및 개선함.

Poem

🍲
메뉴 가격 정수로 바뀌고,
주문엔 세션이 깃들었네.
아이템 목록도 척척 조회,
테이블마다 주문이 또렷해.
코드의 봄바람 살랑 불며,
오늘도 개발은 한 뼘 성장해!
🌱


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3332d38 and 520f5f1.

📒 Files selected for processing (1)
  • src/main/java/com/example/gtable/order/controller/OrderController.java (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/example/gtable/order/controller/OrderController.java
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/main/java/com/example/gtable/order/service/OrderService.java (1)

86-96: 성능 최적화와 빈 결과 처리를 고려해주세요.

현재 구현은 기능적으로 올바르지만, 성능과 사용자 경험 측면에서 개선 여지가 있습니다.

다음 개선사항들을 고려해보세요:

  1. 성능 최적화: Repository에서 직접 OrderItem을 조회하는 방법
  2. 빈 결과 처리: 빈 목록일 때의 명확한 처리
 @Transactional(readOnly = true)
 public List<OrderItemListGetResponseDto> getOrderItems(Long storeId, Long tableId, String sessionId) {
-    // 1. UserOrder 목록 조회 (storeId, tableId, sessionId 기준)
-    List<UserOrder> userOrders = orderRepository.findByStore_StoreIdAndTableIdAndSessionId(storeId, tableId, sessionId);
-
-    // 2. OrderItem으로 변환
-    return userOrders.stream()
-        .flatMap(order -> order.getOrderItems().stream())
-        .map(OrderItemListGetResponseDto::fromEntity)
-        .toList();
+    List<UserOrder> userOrders = orderRepository.findByStore_StoreIdAndTableIdAndSessionId(storeId, tableId, sessionId);
+    
+    if (userOrders.isEmpty()) {
+        return Collections.emptyList(); // 빈 목록 명시적 반환
+    }
+    
+    return userOrders.stream()
+        .flatMap(order -> order.getOrderItems().stream())
+        .map(OrderItemListGetResponseDto::fromEntity)
+        .collect(Collectors.toList());
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59d5308 and 3332d38.

📒 Files selected for processing (9)
  • src/main/java/com/example/gtable/menu/dto/MenuCreateRequest.java (1 hunks)
  • src/main/java/com/example/gtable/menu/dto/MenuCreateResponse.java (1 hunks)
  • src/main/java/com/example/gtable/menu/dto/MenuReadDto.java (1 hunks)
  • src/main/java/com/example/gtable/menu/model/Menu.java (1 hunks)
  • src/main/java/com/example/gtable/order/controller/OrderController.java (4 hunks)
  • src/main/java/com/example/gtable/order/entity/UserOrder.java (4 hunks)
  • src/main/java/com/example/gtable/order/repository/OrderRepository.java (2 hunks)
  • src/main/java/com/example/gtable/order/service/OrderService.java (4 hunks)
  • src/main/java/com/example/gtable/orderitem/dto/OrderItemListGetResponseDto.java (1 hunks)
🔇 Additional comments (12)
src/main/java/com/example/gtable/menu/dto/MenuCreateResponse.java (1)

19-19: 가격 필드의 데이터 타입 변경을 승인합니다.

String에서 Integer로의 타입 변경은 매우 적절한 개선사항입니다. 가격 데이터는 숫자 타입으로 관리하는 것이 데이터 일관성과 타입 안전성 측면에서 훨씬 좋습니다.

src/main/java/com/example/gtable/menu/dto/MenuCreateRequest.java (1)

22-22: 요청 DTO의 가격 필드 타입 변경이 적절합니다.

다른 메뉴 관련 클래스들과 일관성을 유지하면서 Integer 타입으로 변경한 것이 좋습니다. @NotNull 검증도 그대로 유지되어 있어 완벽합니다.

src/main/java/com/example/gtable/menu/dto/MenuReadDto.java (1)

20-20: 읽기 DTO의 가격 필드 타입 변경을 승인합니다.

메뉴 관련 모든 DTO에서 일관되게 Integer 타입으로 변경하신 것이 매우 체계적이고 좋습니다. fromEntity 메서드도 올바르게 구현되어 있습니다.

src/main/java/com/example/gtable/menu/model/Menu.java (2)

34-41: 생성자 매개변수 타입 변경이 일관성 있게 처리되었습니다.

필드 타입 변경에 맞춰 생성자 매개변수도 Integer로 변경하신 것이 좋습니다. 타입 일관성이 잘 유지되고 있습니다.


32-32: 엔티티의 가격 필드 타입 변경을 승인합니다.

엔티티 레벨에서 Integer로 변경하신 것이 매우 적절합니다. 데이터베이스에서 가격을 숫자 타입으로 관리하는 것이 올바른 설계입니다.

데이터베이스 마이그레이션이 필요한지 확인해 주세요. 기존 String 타입 데이터가 있다면 Integer로 안전하게 변환되는지 검증이 필요합니다.

다음 스크립트로 price 필드 사용 현황을 확인할 수 있습니다:

#!/bin/bash
# 가격 필드 관련 데이터베이스 스키마 및 마이그레이션 파일 확인
fd -e sql | xargs grep -l "price"
src/main/java/com/example/gtable/order/repository/OrderRepository.java (2)

4-4: 필요한 import 추가가 적절합니다.

List 타입을 사용하기 위한 import가 정확하게 추가되었습니다.


15-15: UserOrder 엔티티의 Store 관계 매핑(@ManyToOne + @JoinColumn)이 실제로 Store 필드를 가리키는지 확인하기 위해, 아래 스크립트를 실행해 주세요. 매핑 선언과 조인 컬럼 정보를 함께 보여주시면 검토를 이어가겠습니다.

#!/bin/bash
# UserOrder 엔티티의 ManyToOne 매핑 주변 코드(필드명 포함) 확인
rg -n --glob 'UserOrder.java' '@ManyToOne' -A3 -B1 src/main/java/com/example/gtable/order/entity/UserOrder.java

# JoinColumn 어노테이션으로 매핑 컬럼 이름 확인
rg -n --glob 'UserOrder.java' '@JoinColumn' -A3 -B1 src/main/java/com/example/gtable/order/entity/UserOrder.java
src/main/java/com/example/gtable/order/service/OrderService.java (1)

37-38: 메서드 시그니처 변경이 적절합니다.

세션 ID 매개변수 추가로 세션 기반 주문 관리가 가능해졌습니다. 변경사항이 PR 목표와 일치합니다.

src/main/java/com/example/gtable/order/entity/UserOrder.java (3)

47-48: 엔티티 관계 설정이 적절합니다.

OrderItem과의 OneToMany 관계가 올바르게 설정되었습니다. CascadeType.ALLorphanRemoval = true 설정으로 데이터 무결성이 잘 관리될 것 같습니다.


50-50: 세션 ID 필드 추가가 적절합니다.

세션 기반 주문 관리를 위한 sessionId 필드가 올바르게 추가되었습니다.


31-31: Builder 어노테이션 변경에 대한 검증이 필요합니다.

@SuperBuilder에서 @Builder로 변경되었는데, BaseTimeEntity와의 상속 관계에서 문제가 없는지 확인이 필요합니다.

다음 스크립트로 BaseTimeEntity의 Builder 패턴 사용을 확인해주세요:

#!/bin/bash
# BaseTimeEntity에서 SuperBuilder 사용 여부 확인
ast-grep --pattern 'class BaseTimeEntity {
  $$$
}'

# SuperBuilder 어노테이션 사용 확인  
rg -A 3 -B 3 "@SuperBuilder" src/main/java/com/example/gtable/global/entity/BaseTimeEntity.java
src/main/java/com/example/gtable/order/controller/OrderController.java (1)

40-44: 세션 처리 구현이 올바릅니다.

HttpSession을 통한 세션 ID 추출과 서비스 계층으로의 전달이 적절하게 구현되었습니다.

Comment on lines +20 to +28
public static OrderItemListGetResponseDto fromEntity(OrderItem orderItem) {
return OrderItemListGetResponseDto.builder()
.orderId(orderItem.getUserOrder().getId())
.menuName(orderItem.getMenu().getName())
.quantity(orderItem.getQuantity())
.price(orderItem.getMenu().getPrice())
.build();

}
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 안전성 고려가 필요합니다.

fromEntity 메서드에서 orderItem.getUserOrder()orderItem.getMenu() 접근 시 null 체크가 없어 NPE 위험이 있습니다. 안전성을 위해 방어적 프로그래밍을 권장드립니다.

다음과 같이 null 안전성을 추가해보세요:

 public static OrderItemListGetResponseDto fromEntity(OrderItem orderItem) {
+    if (orderItem == null || orderItem.getUserOrder() == null || orderItem.getMenu() == null) {
+        throw new IllegalArgumentException("OrderItem과 연관된 엔티티들이 null일 수 없습니다");
+    }
     return OrderItemListGetResponseDto.builder()
         .orderId(orderItem.getUserOrder().getId())
         .menuName(orderItem.getMenu().getName())
         .quantity(orderItem.getQuantity())
         .price(orderItem.getMenu().getPrice())
         .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 OrderItemListGetResponseDto fromEntity(OrderItem orderItem) {
return OrderItemListGetResponseDto.builder()
.orderId(orderItem.getUserOrder().getId())
.menuName(orderItem.getMenu().getName())
.quantity(orderItem.getQuantity())
.price(orderItem.getMenu().getPrice())
.build();
}
public static OrderItemListGetResponseDto fromEntity(OrderItem orderItem) {
+ if (orderItem == null || orderItem.getUserOrder() == null || orderItem.getMenu() == null) {
+ throw new IllegalArgumentException("OrderItem과 연관된 엔티티들이 null일 수 없습니다");
+ }
return OrderItemListGetResponseDto.builder()
.orderId(orderItem.getUserOrder().getId())
.menuName(orderItem.getMenu().getName())
.quantity(orderItem.getQuantity())
.price(orderItem.getMenu().getPrice())
.build();
}
🤖 Prompt for AI Agents
In
src/main/java/com/example/gtable/orderitem/dto/OrderItemListGetResponseDto.java
between lines 20 and 28, the fromEntity method accesses orderItem.getUserOrder()
and orderItem.getMenu() without null checks, risking NullPointerException. Add
defensive null checks before accessing these methods, and handle null cases
appropriately, such as returning default values or throwing informative
exceptions, to ensure null safety.

Comment on lines 54 to 67
@GetMapping("/items/{storeId}/{tableId}")
@Operation(summary = "테이블별 주문 아이템 조회", description = "비로그인(세션) 기준으로 테이블의 내 주문 목록만 조회")
@ApiResponse(responseCode = "200", description = "주문 조회")
public ResponseEntity<List<OrderItemListGetResponseDto>> getOrderItems(
@PathVariable Long storeId,
@PathVariable Long tableId,
HttpSession session
) {
// 세션ID 추출 (Spring이 세션 자동 관리)
String sessionId = session.getId();

List<OrderItemListGetResponseDto> orderItems = orderService.getOrderItems(storeId, tableId, sessionId);
return ResponseEntity.ok(orderItems);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

API 응답 일관성과 세션 보안을 고려해주세요.

새로운 엔드포인트가 잘 구현되었지만, 몇 가지 개선사항을 제안드립니다.

  1. API 응답 일관성: 다른 엔드포인트와 동일하게 ApiUtils.success()로 래핑
  2. 세션 상태 검증: 세션 유효성 체크 추가
 @GetMapping("/items/{storeId}/{tableId}")
 @Operation(summary = "테이블별 주문 아이템 조회", description = "비로그인(세션) 기준으로 테이블의 내 주문 목록만 조회")
 @ApiResponse(responseCode = "200", description = "주문 조회")
-public ResponseEntity<List<OrderItemListGetResponseDto>> getOrderItems(
+public ResponseEntity<?> getOrderItems(
     @PathVariable Long storeId,
     @PathVariable Long tableId,
     HttpSession session
 ) {
+    if (session.isNew()) {
+        throw new IllegalStateException("유효하지 않은 세션입니다");
+    }
+    
     String sessionId = session.getId();
     List<OrderItemListGetResponseDto> orderItems = orderService.getOrderItems(storeId, tableId, sessionId);
-    return ResponseEntity.ok(orderItems);
+    return ResponseEntity.ok(ApiUtils.success(orderItems));
 }
📝 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
@GetMapping("/items/{storeId}/{tableId}")
@Operation(summary = "테이블별 주문 아이템 조회", description = "비로그인(세션) 기준으로 테이블의 내 주문 목록만 조회")
@ApiResponse(responseCode = "200", description = "주문 조회")
public ResponseEntity<List<OrderItemListGetResponseDto>> getOrderItems(
@PathVariable Long storeId,
@PathVariable Long tableId,
HttpSession session
) {
// 세션ID 추출 (Spring이 세션 자동 관리)
String sessionId = session.getId();
List<OrderItemListGetResponseDto> orderItems = orderService.getOrderItems(storeId, tableId, sessionId);
return ResponseEntity.ok(orderItems);
}
@GetMapping("/items/{storeId}/{tableId}")
@Operation(summary = "테이블별 주문 아이템 조회", description = "비로그인(세션) 기준으로 테이블의 내 주문 목록만 조회")
@ApiResponse(responseCode = "200", description = "주문 조회")
public ResponseEntity<?> getOrderItems(
@PathVariable Long storeId,
@PathVariable Long tableId,
HttpSession session
) {
if (session.isNew()) {
throw new IllegalStateException("유효하지 않은 세션입니다");
}
String sessionId = session.getId();
List<OrderItemListGetResponseDto> orderItems = orderService.getOrderItems(storeId, tableId, sessionId);
return ResponseEntity.ok(ApiUtils.success(orderItems));
}
🤖 Prompt for AI Agents
In src/main/java/com/example/gtable/order/controller/OrderController.java around
lines 54 to 67, the getOrderItems method should be updated to ensure API
response consistency and session security. Wrap the returned orderItems list
with ApiUtils.success() to match the response format of other endpoints.
Additionally, add a check to verify the session is valid before proceeding; if
the session is invalid or expired, return an appropriate error response to
prevent unauthorized access.

@HyemIin HyemIin merged commit 1de7df7 into develop Jun 20, 2025
1 check passed
@HyemIin HyemIin deleted the feature/#30-주문CRUD branch June 20, 2025 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants