[SpringBoot]스프링부트 쇼핑몰 프로젝트 with JPA(주문)

hwa.haha·2022년 11월 24일
0

SpringBoot

목록 보기
6/7
post-thumbnail

고객이 상품을 주문하면 현재 상품의 재고에서 주문 수량만큼 재고를 감소 시켜야합니다.

상품의 주문수량보다 재고의 수가 적을 때 발생시킬 exception을 정의하겠습니다.
com.shop 패키지 아래에 exception 패키지를 생성한 후 runtimeExecprion을 상속받는 OutOfStockException클래스를 생성합니다.

OutOfStockException

package com.shop.shop.exception;

public class OutOfStockException extends  RuntimeException{

    public  OutOfStockException(String message){
        super(message);
    }
}

item 추가


 public void removeStock(int stockNumber){
        //상품의 재고수량에서 주문 후 남은 재고 수량을 구합니다.
        int restStock = this.stockNumber -stockNumber;
        if (restStock<0){
        //상품의 재고가 주문 수량보다 작은 경우 재고 부족 예외를 발생시킵니다.
            throw new OptimisticLockException("상품의 재고가 부족합니다.(현재 재고 수량:" + this.stockNumber +")");
        }
        //주문 후 남은 재고 수량을 상품의 현재 재고 값으로 할당합니다.
        this.stockNumber = restStock;
    }
    

OrderItem

package com.shop.shop.entity;


import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@Getter
@Setter
public class OrderItem {

    @Id
    @GeneratedValue
    @Column(name = "order_item_id")
    private Long id;

    @ManyToOne(fetch =FetchType.LAZY)
    @JoinColumn(name = "item_id")
    private  Item item;

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

    private int orderPrice;

    private int count;

    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;
    }
   // private  LocalDateTime regTime;
   // private  LocalDateTime updateTime;

}

Order

package com.shop.shop.entity;

import com.shop.shop.constant.OrderStatus;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name ="orders")
@Getter
@Setter
public class Order {

    @Id
    @GeneratedValue
    @Column(name = "order_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)//주문만 알수있음 멤버도 내용을 알려면 양방향이 되어야한다.
    @JoinColumn(name = "member_id")
    private Member member;

    private LocalDateTime orderDate; //주문일

    @Enumerated(EnumType.STRING)
    private OrderStatus orderStatus; //주문상태

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true,fetch = FetchType.LAZY) //한개 삭제,한개 저장
    //주인이 아닌쪽은 연관관계매핑시 mappyBy속성의 값으로 연관관계의 주인설정(변수명)
    private List<OrderItem>  orderItems = new ArrayList<>();
    //객체선언하면 연관관계 매핑해주어야한다.

    private  LocalDateTime regTime;

    private  LocalDateTime updateTime;

    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;
    }

    public  int getTotalPrice(){
        int totalPrice = 0;
        for(OrderItem orderItem : orderItems){
            totalPrice += orderItem.getTotalPrice();
        }
        return  totalPrice;
    }

}

OrderDto

import lombok.Getter;
import lombok.Setter;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

@Getter
@Setter
public class OrderDto {

    @NotNull(message = "상품 아이디는 필수 입력 값입니다.")
    private  Long itemId;

    @Min(value = 1, message = "최소 주문 수량은 1개입니다.")
    @Max(value = 999,message = "최대 주문 수량은 999개 입니다.")
    private int count;

}

OrderService

package com.shop.shop.service;


import com.shop.shop.dto.OrderDto;
import com.shop.shop.entity.Item;
import com.shop.shop.entity.Member;
import com.shop.shop.entity.Order;
import com.shop.shop.entity.OrderItem;
import com.shop.shop.repository.ItemImgRepository;
import com.shop.shop.repository.ItemRepository;
import com.shop.shop.repository.MemberRepository;
import com.shop.shop.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityNotFoundException;
import java.util.ArrayList;
import java.util.List;

@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 orderItem =
        OrderItem.createOrderItem(item, orderDto.getCount());
        orderItemList.add(orderItem);
        Order order = Order.createOrder(member, orderItemList);
        orderRepository.save(order);

        return  order.getId();

    }
}

OrderController

package com.shop.shop.controller;


import com.shop.shop.dto.OrderDto;
import com.shop.shop.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.Valid;
import java.security.Principal;
import java.util.List;

@Controller
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;

    @PostMapping(value = "/order")
    public @ResponseBody 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);
        }

        String email = principal.getName();
        Long orderId;
        try {
            orderId = orderService.order(orderDto,email);
        }catch (Exception e){
            return  new ResponseEntity<String>(e.getMessage(),HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity<Long>(orderId,HttpStatus.OK);
    }

}

주문취소

Item


 public void  addStock(int stockNumber){
        this.stockNumber += stockNumber;
    }

OrderItem

   public  void cancel(){
        this.getItem().addStock(count);
    }

Order

public  void  cancelOrder(){
        this.orderStatus = OrderStatus.CANCEL;
        
        for (OrderItem orderItem : orderItems){
            orderItem.cancel();
        }
    }
profile
개발자로 차근차근

0개의 댓글