package jace.shim.springcamp2017.product.model;
import jace.shim.springcamp2017.core.domain.AggregateRoot;
import jace.shim.springcamp2017.core.exception.EventApplyException;
import jace.shim.springcamp2017.product.exception.InsufficientInventoryQuantityException;
import jace.shim.springcamp2017.product.model.command.ProductCommand;
import jace.shim.springcamp2017.product.model.event.*;
import lombok.Getter;
import java.time.LocalDateTime;
/**
* Created by jaceshim on 2017. 3. 3..
*/
@Getter
public class Product extends AggregateRoot<Long> {
/** 상품 아이디 */
private Long productId;
/** 상품 명 */
private String name;
/** 상품 가격 */
private int price;
/** 상품 수량 */
private int inventory;
/** 상품 이미지 경로 */
private String imagePath;
/** 상품 설명 */
private String description;
/** 상품 등록일시 */
private LocalDateTime created;
/** 상품 수정일시 */
private LocalDateTime updated;
Product() {
super();
}
Product(Long productId) {
super(productId);
this.productId = productId;
}
Product(Long productId, String name, int price, int quantity, String imagePath, String description) {
super(productId);
applyChange(new ProductCreated(productId, name, price, quantity, imagePath, description));
}
public Product(Long productId, String name, int price, int inventory) {
super(productId);
this.productId = productId;
this.name = name;
this.price = price;
this.inventory = inventory;
}
/**
* 상품 등록
*
* @param productCreateCommand
* @return
* @throws EventApplyException
*/
public static Product create(Long productId, ProductCommand.CreateProduct productCreateCommand) {
Product product = new Product(productId, productCreateCommand.getName(), productCreateCommand.getPrice(),
productCreateCommand.getQuantity(), productCreateCommand.getImagePath(),
productCreateCommand.getDescription());
return product;
}
/**
* 상품아이디 생성
* @return
*/
private static long createProductId() {
long min = 1000000L;
long max = 9999999L;
return min + (long) (Math.random() * (max - min));
}
/**
* 상품생성 이벤트 반영
*
* @param event
*/
public void apply(ProductCreated event) {
this.productId = event.getProductId();
this.name = event.getName();
this.price = event.getPrice();
this.inventory = event.getInventory();
this.imagePath = event.getImagePath();
this.description = event.getDescription();
this.created = event.getCreated();
}
/**
* 상품명 변경
*
* @param productChangeNameCommand
* @throws EventApplyException
*/
public void changeName(ProductCommand.ChangeName productChangeNameCommand) {
applyChange(new ProductNameChanged(this.getProductId(), productChangeNameCommand.getName()));
}
/**
* 상품명 변경 이벤트 반영
* @param event
*/
public void apply(ProductNameChanged event) {
this.name = event.getName();
this.updated = event.getUpdated();
}
/**
* 상품 가격 변경
* @param productChangePriceCommand
*/
public void changePrice(ProductCommand.ChangePrice productChangePriceCommand) {
applyChange(new ProductPriceChanged(this.getProductId(), productChangePriceCommand.getPrice()));
}
/**
* 상품 가격 변경 이벤트 반영
* @param event
*/
public void apply(ProductPriceChanged event) {
this.price = event.getPrice();
this.updated = event.getUpdated();
}
/**
* 상품 판매수량 증가
* @param productIncreaseQuantityCommand
* @throws EventApplyException
*/
public void increaseQuantity(ProductCommand.IncreaseQuantity productIncreaseQuantityCommand) {
applyChange(new ProductInventoryIncreased(this.getProductId(), productIncreaseQuantityCommand.getQuantity()));
}
/**
* 상품 판매수량 증가 이벤트 반영
* @param event
*/
public void apply(ProductInventoryIncreased event) {
this.inventory = this.getInventory() + event.getInventory();
this.updated = event.getUpdated();
}
/**
* 상품 판매수량 감소
* @param productDecreaseQuantityCommand
* @throws EventApplyException
*/
public void decreaseQuantity(ProductCommand.DecreaseQuantity productDecreaseQuantityCommand) {
if (this.getInventory() < productDecreaseQuantityCommand.getQuantity()) {
throw new InsufficientInventoryQuantityException(this.getProductId() + " is not insufficient inventory quantity");
}
applyChange(new ProductInventoryDecreased(this.getProductId(), productDecreaseQuantityCommand.getQuantity()));
}
/**
* 상품 판매수량 감소 이벤트 반영
* @param event
*/
public void apply(ProductInventoryDecreased event) {
this.inventory = this.getInventory() - event.getInventory();
this.updated = event.getUpdated();
}
}