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
12 changes: 12 additions & 0 deletions src/main/java/com/campustable/be/domain/menu/entity/Menu.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.campustable.be.domain.category.entity.Category;
import com.campustable.be.domain.menu.dto.MenuUpdateRequest;
import com.campustable.be.global.exception.CustomException;
import com.campustable.be.global.exception.ErrorCode;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
Expand Down Expand Up @@ -84,4 +86,14 @@ public void update(MenuUpdateRequest request) {
}
}

public void decreaseStockQuantity(int quantity) {
if(this.stockQuantity - quantity < 0) {
throw new CustomException(ErrorCode.MENU_OUT_OF_STOCK);
}
else if(this.stockQuantity - quantity == 0) {
this.available = false;
}
this.stockQuantity -= quantity;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.campustable.be.domain.order.controller;


import com.campustable.be.domain.order.dto.OrderResponse;
import com.campustable.be.domain.order.service.OrderService;
import com.campustable.be.global.aop.LogMonitoringInvocation;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/orders")
public class OrderController implements OrderControllerDocs {

private final OrderService orderService;

@Override
@LogMonitoringInvocation
@PostMapping
public ResponseEntity<OrderResponse> createOrder() {
return ResponseEntity.ok(orderService.createOrder());
}

@Override
@LogMonitoringInvocation
@PatchMapping("/{orderId}/categories/{categoryId}/ready")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public ResponseEntity<Void> updateCategoryToReady(
@PathVariable Long orderId,
@PathVariable Long categoryId) {
orderService.updateCategoryToReady(orderId,categoryId);
return ResponseEntity.ok().build();
}

@Override
@LogMonitoringInvocation
@PatchMapping("/{orderId}/categories/{categoryId}/complete")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public ResponseEntity<Void> updateCategoryToComplete(
@PathVariable Long orderId,
@PathVariable Long categoryId
) {
orderService.updateCategoryToComplete(orderId,categoryId);
return ResponseEntity.ok().build();
}

@Override
@LogMonitoringInvocation
@GetMapping
public ResponseEntity<List<OrderResponse>> getMyOrders() {
return ResponseEntity.ok(orderService.getMyOrders());
}

@Override
@GetMapping("/users/{userId}")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public ResponseEntity<List<OrderResponse>> getOrdersByUserId(@PathVariable Long userId) {
return ResponseEntity.ok(orderService.getOrdersByUserId(userId));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.campustable.be.domain.order.controller;

import com.campustable.be.domain.order.dto.OrderResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;

@Tag(name = "Order API", description = "주문 관련 API (생성, 조회, 상태 변경)")
public interface OrderControllerDocs {

@Operation(summary = "주문 생성", description = "현재 사용자의 장바구니에 담긴 메뉴들로 주문을 생성합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "주문 생성 성공"),
@ApiResponse(responseCode = "400", description = "재고 부족"),
@ApiResponse(responseCode = "404", description = "장바구니가 비어있거나 사용자를 찾을 수 없음")
})
ResponseEntity<OrderResponse> createOrder();

@Operation(summary = "카테고리별 조리 완료 처리 (관리자)", description = "특정 주문(OrderId) 내의 특정 카테고리(CategoryId) 메뉴들을 모두 '조리 완료'로 변경합니다.")
ResponseEntity<Void> updateCategoryToReady(
@Parameter(description = "주문 ID", example = "1") @PathVariable Long orderId,
@Parameter(description = "카테고리 ID", example = "2") @PathVariable Long categoryId
);

@Operation(summary = "카테고리별 수령 완료 처리 (관리자)", description = "특정 주문(OrderId) 내의 특정 카테고리(CategoryId) 메뉴들을 모두 '수령 완료'로 변경합니다.")
ResponseEntity<Void> updateCategoryToComplete(
@Parameter(description = "주문 ID", example = "1") @PathVariable Long orderId,
@Parameter(description = "카테고리 ID", example = "2") @PathVariable Long categoryId
);

@Operation(summary = "내 주문 내역 조회", description = "사용자의 주문 내역을 조회합니다. (진행 중인 주문이 상단에 노출됨)")
@ApiResponse(responseCode = "200", description = "조회 성공")
ResponseEntity<List<OrderResponse>> getMyOrders();

@Operation(summary = "특정 유저 주문 조회 (관리자)", description = "관리자가 특정 유저(User ID)의 모든 주문 내역을 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "조회 성공"),
@ApiResponse(responseCode = "403", description = "관리자 권한 없음"),
@ApiResponse(responseCode = "404", description = "해당 유저를 찾을 수 없음")
})
ResponseEntity<List<OrderResponse>> getOrdersByUserId(
@Parameter(description = "조회할 유저 ID", example = "5")
@PathVariable Long userId
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.campustable.be.domain.order.dto;

import com.campustable.be.domain.order.entity.OrderItem;
import com.campustable.be.domain.order.entity.OrderStatus;
import lombok.AccessLevel;
import lombok.Getter;

@Getter
public class OrderItemDto {

private Long orderItemId;
private Long menuId;
private String menuName;
private int orderPrice;
private int quantity;
private int subTotal;
private String menuUrl;
private OrderStatus status;
private Long categoryId;

public OrderItemDto(OrderItem orderItem) {
this.orderItemId = orderItem.getOrderItemId();
this.menuId = orderItem.getMenu().getId();
this.menuName = orderItem.getMenu().getMenuName();
this.orderPrice = orderItem.getOrderPrice(); //주문 당시가격
this.quantity = orderItem.getQuantity();
this.subTotal = orderItem.getOrderPrice() * orderItem.getQuantity();
this.menuUrl = orderItem.getMenu().getMenuUrl();
this.status = orderItem.getStatus();
this.categoryId=orderItem.getCategoryId();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.campustable.be.domain.order.dto;

import com.campustable.be.domain.order.entity.Order;
import java.time.LocalDateTime;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@AllArgsConstructor // Builder와 함께 사용 시 관례적으로 추가
public class OrderResponse {

private Long orderId;
private int totalPrice;
private LocalDateTime orderDate;
private List<OrderItemDto> orderItems;

public static OrderResponse from(Order order) {
return OrderResponse.builder()
.orderId(order.getOrderId())
.totalPrice(order.getTotalPrice())
.orderDate(order.getCreatedAt()) // BaseTimeEntity의 생성일
.orderItems(order.getOrderItems().stream()
.map(OrderItemDto::new)
.toList())
.build();
}
}
62 changes: 62 additions & 0 deletions src/main/java/com/campustable/be/domain/order/entity/Order.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.campustable.be.domain.order.entity;

import com.campustable.be.domain.user.entity.User;
import com.campustable.be.global.common.BaseTimeEntity;
import com.campustable.be.global.exception.CustomException;
import com.campustable.be.global.exception.ErrorCode;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name="orders")
public class Order extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="order_id")
private Long orderId;

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

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();

private int totalPrice;


public static Order createOrder(User user, List<OrderItem> orderItems) {
Order order = new Order();
order.setUser(user);
for (OrderItem orderItem : orderItems) {
order.addOrderItem(orderItem);
}
order.setTotalPrice(orderItems.stream().mapToInt(OrderItem::getTotalPrice).sum());
return order;
}

public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
orderItem.setOrder(this);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.campustable.be.domain.order.entity;


import com.campustable.be.domain.menu.entity.Menu;
import com.campustable.be.global.exception.CustomException;
import com.campustable.be.global.exception.ErrorCode;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
public class OrderItem {

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

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="order_id")
private Order order;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="menu_id")
private Menu menu;

@Enumerated(EnumType.STRING)
private OrderStatus status;

private String menuName;
private int orderPrice;
private int quantity;

private Long categoryId;

public static OrderItem createOrderItem(Menu menu, int orderPrice, int quantity) {
OrderItem orderItem = new OrderItem();
orderItem.setMenu(menu);
orderItem.setStatus(OrderStatus.PREPARING);
orderItem.setMenuName(menu.getMenuName());
orderItem.setOrderPrice(orderPrice);
orderItem.setQuantity(quantity);
orderItem.setCategoryId(menu.getCategory().getCategoryId());
return orderItem;
}

public int getTotalPrice() {
return getOrderPrice() * getQuantity();
}

public void markAsReady() {
if (this.status != OrderStatus.PREPARING) {
throw new CustomException(ErrorCode.INVALID_ORDER_STATUS);
}
this.status = OrderStatus.READY;
}

// 수령 대기 -> 주문 완료
public void markAsCompleted() {
if (this.status != OrderStatus.READY) {
throw new CustomException(ErrorCode.INVALID_ORDER_STATUS);
}
this.status = OrderStatus.COMPLETED;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.campustable.be.domain.order.entity;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum OrderStatus {

PREPARING("조리 중"),

READY("수령 대기"),

COMPLETED("주문 완료");

private final String description;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.campustable.be.domain.order.repository;

import com.campustable.be.domain.order.entity.OrderItem;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderItemRepository extends JpaRepository<OrderItem, Long> {

List<OrderItem> findByOrderOrderIdAndCategoryId(Long orderId, Long categoryId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.campustable.be.domain.order.repository;

import com.campustable.be.domain.order.entity.Order;
import java.util.Collection;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderRepository extends JpaRepository<Order, Long> {

List<Order> findByUserUserIdOrderByCreatedAtDesc(Long userId);
}
Loading