package jace.shim.springcamp2017.order.model; import jace.shim.springcamp2017.core.domain.AggregateRoot; import jace.shim.springcamp2017.member.model.Member; import jace.shim.springcamp2017.order.exception.OrderInventoryExceedLimit; import jace.shim.springcamp2017.order.model.event.OrderCreated; import jace.shim.springcamp2017.product.model.Product; import lombok.EqualsAndHashCode; import lombok.Getter; import java.time.LocalDateTime; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Created by jaceshim on 2017. 3. 28.. */ @Getter @EqualsAndHashCode public class Order extends AggregateRoot<Long> { /** 주문번호 */ private Long orderId; /** 주문회원 */ private Member orderMember; /** 배송정보 */ private Delivery delivery; /** 주문 상품 */ private Set<OrderItem> orderItems = new HashSet<>(); private LocalDateTime created; Order() { super(); } Order(Long orderId, Member orderMember, Delivery delivery, List<OrderItem> checkoutItems) { super(orderId); this.orderId = orderId; this.orderMember = orderMember; this.delivery = delivery; this.created = LocalDateTime.now(); for (OrderItem orderItem : checkoutItems) { this.with(orderItem); } applyChange(new OrderCreated(orderId, orderMember, delivery, orderItems, created)); } /** * 주문 이벤트 반영 * @param orderCreated */ public void apply(OrderCreated orderCreated) { this.orderId = orderCreated.getOrderId(); this.orderMember = orderCreated.getOrderMember(); this.delivery = orderCreated.getDelivery(); this.orderItems = orderCreated.getOrderItems(); } public static Order order(Long orderId, Member orderMember, Delivery delivery, List<OrderItem> orderItems) { final Order order = new Order(orderId, orderMember, delivery, orderItems); return order; } public Order with(Product product, int quantity) { return with(new OrderItem(product, quantity)); } private Order with(OrderItem orderItem) { if (inventoryExceedLimit(orderItem)) { throw new OrderInventoryExceedLimit(orderItem.getProduct().getProductId(), orderItem.getQuantity()); } for (OrderItem item : orderItems) { if (item.isProductEqual(orderItem)) { item.merge(orderItem); return this; } } this.orderItems.add(orderItem); return this; } /** * 재고수량 확인 * * @param orderItem * @return */ private boolean inventoryExceedLimit(OrderItem orderItem) { final int currentInventory = orderItem.getProduct().getInventory(); return currentInventory < orderItem.getQuantity(); } public int getTotalPrice() { return orderItems.stream().mapToInt(orderItem -> orderItem.getProduct().getPrice() * orderItem.getQuantity()).sum(); } public Order with(String address, String phone, String deliveryMessage) { this.delivery = new Delivery(address, phone, deliveryMessage); return this; } }