// 상품 주문 수량보다 현재 재고의 수가 적을 때 발생시킬 Exception
public class OutOfStockException extends RuntimeException {
public OutOfStockException(String message) {
super(message);
}
}
2. 상품 재고 변경
(기존 재고 - 주문 수량 재고) 로 stockNumber 수정
만약 0 보다 작다면 재고가 부족한 것이므로 Exception 발생
// item 클래스
// 상품 재고 변경
public void removeStock(int stockNumber) {
// (기존 재고 - 주문 수량 재고)
int restStock = this.stockNumber - stockNumber;
// 만약 0보다 작다면 재고가 부족한 것이므로 Exception 발생
if(restStock < 0) {
throw new OutOfStockException("상품의 재고가 부족합니다. (현재 재고 수량 : " + this.stockNumber + ")");
}
this.stockNumber = restStock;
}
3. OrderItem 객체
주문 상품과 주문 수량 정보를 가지고 있는 OrderItem Entity 에 객체 생성 메소드 추가
// 주문 상품과 주문 수량 정보를 가지고 있는 메소드
public static OrderItem createOrderItem(Item item, int count) {
OrderItem orderItem = new OrderItem();
orderItem.setItem(item);
orderItem.setCount(count);
orderItem.setOrderPrice(item.getPrice());
item.removeStock(count);
return orderItem;
}
public int getTotalPrice() {
return orderPrice * count;
}
4. Order 객체
OrderItem 객체를 연결하고 OrderItem 객체에 자신을 연결하는 메소드 추가
OrderItem 객체를 이용하여 주문 객체를 만드는 메소드 추가
각 주문 상품의 TotalPrice를 구한뒤 모두 더하는 메소드 추가
// OrderItem 객체 연결 및 자신을 연결하는 메소드
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem); // 주문 객체에 주문 상품 객체 연결
orderItem.setOrder(this); // 주문 상품 객체에 주문 객체 연결(연관 관계 주인)
}
// 주문 객체를 만드는 메소드
public static Order createOrder(Member member, List<OrderItem> orderItemList) {
Order order = new Order();
order.setMember(member);
for(OrderItem orderItem : orderItemList) {
order.addOrderItem(orderItem);
}
order.setOrderStatus(OrderStatus.ORDER);
order.setOrderDate(LocalDateTime.now());
return order;
}
// 각 주문 상품의 TotalPrice를 구한 뒤 모두 더하는 메소드
public int getTotalPrice() {
int totalPrice = 0;
// 각 상품마다 TotalPrice를 구하고 모두 더함
for(OrderItem orderItem : orderItems) {
totalPrice += orderItem.getTotalPrice();
}
return totalPrice;
}
5. 주문 정보 Dto
제품 상세 페이지 화면에서 보내는 주문 정보 (상품, 수량)를 위한 DTO 객체 생성
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class OrderDto {
@NotNull(message = "상품 아이디는 필수 입력 값입니다.")
private Long itemId;
@Min(value = 1, message = "최소 주문 수량은 1개입니다.")
@Max(value = 999, message = "최대 주문 수량은 999개입니다.")
private int count;
}
6. OrderService
상품과 주문한 고객을 조회
주문 상품 객체 생성 -> 주문 객체 생성
@Service
@Transactional
@RequiredArgsConstructor
public class OrderService {
private final ItemRepository itemRepository; // 상품을 불러와서 재고 변경해야 함
private final MemberRepository memberRepository; // 멤버를 불러와서 연결해야 함
private final OrderRepository orderRepository; // 주문 객체를 저장해야 함
private final ItemImgRepository itemImgRepository; // 상품 대표 이미지를 출력해야함
// 상품과 주문한 고객 조회
public Long order(OrderDto orderDto, String email) {
Item item = itemRepository.findById(orderDto.getItemId()).orElseThrow(EntityNotFoundException::new);
Member member = memberRepository.findByEmail(email);
List<OrderItem> orderItemList = new ArrayList<>();
// OrderItem.createOrderItem -> static 메소드
OrderItem orderItem = OrderItem.createOrderItem(item, orderDto.getCount());
orderItemList.add(orderItem);
// Order.createOrder -> static 메소드
Order order = Order.createOrder(member, orderItemList);
orderRepository.save(order);
return order.getId();
}
7. OrderController
비동기 방식으로 Json 데이터를 주고 받음
@RequestBody : http 요청의 body 부분 데이터를 자바 객체로 변환해서 받음
@ResponseBody : 자바 객체를 http 응답 body 부분으로 보냄 (ResponseEntity 자료형)
입력값에 문제가 있을 시 필드 에러 정보들을 ResponseEntity 객체에 담아서 반환
현재 로그인한 유저의 정보를 담고 있는 Principal 객체에서 유저의 email 추출
정상적으로 동작 시 생성된 주문 객체의 Id 와 상태코드 200을 보냄
@Controller
@RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;
@PostMapping("/order")
@ResponseBody
public ResponseEntity order(@RequestBody @Valid OrderDto orderDto, BindingResult bindingResult, Principal principal) {
if(bindingResult.hasErrors()) {
StringBuilder sb = new StringBuilder();
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for(FieldError fieldError : fieldErrors) {
sb.append(fieldError.getDefaultMessage());
}
return new ResponseEntity<String>(sb.toString(), HttpStatus.BAD_REQUEST);
}
// 현재 로그인한 유저의 정보를 담고 있는 Principal 객체에서 유저의 email 추출
String email = principal.getName();
Long orderId;
try {
orderId = orderService.order(orderDto, email);
} catch (Exception e) {
return new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
// 정상 작동 시, 생성된 주문 객체의 id와 상태코드 200 보냄
return new ResponseEntity<Long>(orderId, HttpStatus.OK);
}