주문 금액을 계산하기위해 DiscountPolicy인터페이스에 의존한다. 이렇게 하면 실행 시점에 금액을 계산 할 수 있게 된다.
다른 할인과 조합될 수 있게 DiscountPolicy타입의 next라는 인스턴스 변수를 포함한다. calculatePrice()
는 next인스턴스에게 먼저 가격을 계산하게 한 후 추가 할인을 적용하기 위해 afterCalculated
메서드를 호출한다. addtionalDiscountPolicy를 상속 받은 자식클래스는 afterCalculated()
를 적절히 구현해준다.
Point
- id
- 고객id
- 금액
- 타입
- 거래일자
- 만료일자
- 남은포인트
- 상태(적립 or 사용)
Point_history
- id
- 고객id
- 거래포인트
- 타입
- 처리일자
- 만료일자
- 상태(적립 or 사용)
두 엔티티 모두 JPA Auditing 기능을 사용하였고, Point엔티티의 경우 Point를 저장할때 history
를 남기기 위해 PointEntityListener
를 만들었다.
주석 부분에 어떤 코드가 들어가야할지 고민 했다.
요구사항을 보면 포인트를 사용할 경우 먼저 적립된 포인트부터 순차적으로 사용되어야 한다.
ex)
history
에 다음과 같이 있다면,
적립(100), 사용(-10), 적립(100)
사용(-10)은 맨 앞에 적립(100 + -10) = 90 이고 이때 150포인트를 사용하려 한다면 히스토리는 다음과 같아야한다.
사용(-150)은 앞서 사용되고 남은 90을 먼저 사용처리 해야한다.즉,history
에는 -90, -60 이 되어야 한다.
✅구현하기 위해 내가 생각한 방법은 에서 유저의 pointhistory
에서 사용(-) 포인트와 적립(+) 포인트를 따로 구한 후 먼저 적립된 포인트 부터 차례대로 사용 포인트와 더해서 현재 남은 포인트를 구한다음 history에 남기는걸로 했다.
PointEntityListener의 prePersistAndPreUpdate메서드 중간부분 (전체 코드는 깃에 올려두었다.)
사용할 포인트 + 앞에 남은 포인트 했을때 0보다 작다는 것은 앞에 남은 포인트보다 사용할 포인트가 더 크기 때문에 앞에 남은 포인트를 전부 사용 처리해서 history
에 남긴다.
0보다 크다는 것은 위의 (100 + -10)처럼 사용포인트가 앞에 남은 포인트보다 작다는의미이기 때문에 사용포인트를 history
에 남긴다.
포인트를 사용해서 가격을 계산하고, 주문 후에 포인트가 적립되는것은 orderService에서 일어난다.
orderService에 과하게 의존하는것을 줄이기 위해 EventPublisher
를 사용했다.
@EventListener 어노테이션으로 리스너를 등록하고,
등록된 리스너가 이벤트가 발생 했을때 해당 이벤트를 처리 해준다.
orderService에서 ApplicationEventPublisher를 주입받고, 아래와 같이 이벤트를 발생 시켜주면된다.