-

주문상태 변경 조건과 변경 가능 여부를 Map으로 관리하기

1. 주문상태 변경 조건

주문상태 값은 OrderState ENUM으로 관리하며, 변경 조건은 다음과 같습니다.

상태명 변경 가능 상태 (이전 상태)
주문완료 (ORDER_COMPLETED) (기본 상태) *변경 불가
주문취소요청 (ORDER_CANCEL_REQUEST) 주문완료 (ORDER_COMPLETED)
배송준비중 (PREPARING_SHIPMENT) 주문완료 (ORDER_COMPLETED)
배송중 (SHIPPING) 배송준비중 (PREPARING_SHIPMENT)
배송완료 (DELIVERED) 배송중 (SHIPPING)
취소완료 (CANCELED) 주문취소요청 (ORDER_CANCEL_REQUEST)
반품요청 (RETURN_REQUESTED) 배송완료 (DELIVERED)
교환요청 (EXCHANGE_REQUESTED) 배송완료 (DELIVERED)
반품완료 (RETURNED) 반품요청 (RETURN_REQUESTED)
교환완료 (EXCHANGED) 교환요청 (EXCHANGE_REQUESTED)
구매확정 (CONFIRMED) 배송완료 (DELIVERED)

 

2. 기존에 사용하던 변경 가능 여부 확인 방식

기존에는 OrderService 내부에 단순 switch문으로 구성된 메서드를 작성하여 사용했습니다.

You must be kidding ...

상태를 변경 시, 기존 상태 값을 확인하여 변경 가능한 상태가 아니라면 에러 메시지를 보냅니다.

구조가 반복적이며 Service 안에 많은 라인을 차지하고 있기 때문에 리팩토링이 필요하다고 생각했습니다.

 

3. Map을 이용하여 변경 가능 여부 관리

public static Map<OrderStatus, OrderStatus> statusUpdatable = Map.of(
    ORDER_CANCEL_REQUEST, ORDER_COMPLETED,
    PREPARING_SHIPMENT, ORDER_COMPLETED,
    SHIPPING, PREPARING_SHIPMENT,
    DELIVERED, SHIPPING,
    CANCELED, ORDER_CANCEL_REQUEST,
    RETURN_REQUESTED, DELIVERED,
    EXCHANGE_REQUESTED, DELIVERED,
    CONFIRMED, DELIVERED,
    RETURNED, RETURN_REQUESTED,
    EXCHANGED, EXCHANGE_REQUESTED
);

Key를 바꾸려는 주문상태, Value를 변경이 가능한 현재 주문상태로 매핑하여 OrderStatus Enum 코드에 추가합니다.

 

4. 주문상태 변경 가능 확인 메서드

// 주문상태 변경 가능 여부 (에러처리 핸들러 적용 전)
public void isStatusUpdatable(OrderStatus originStatus, OrderStatus requestStatus) {
    if(requestStatus == OrderStatus.CONFIRMED) {
        throw new IllegalArgumentException("주문완료 상태로 변경할 수 없습니다.");
    }

    if (!statusUpdatable.get(requestStatus).equals(originStatus)) {
        throw new IllegalArgumentException(
            String.format("'%s' 상태에서는 '%s' 상태로 변경할 수 없습니다.", originStatus, requestStatus)
        );
    }
}

// isStatusUpdatable 사용
isStatusUpdatable(originStatus, requestStatus); // 주문상태 변경 가능 여부

order.updateOrderStatus(requestStatus);
log.info("주문상태 변경 완료 >> {}", requestDto.orderStatus());

Service에 메서드를 구현하여 주문상태 가능 여부를 확인하고, 주문상태를 적용합니다. 

* 어떠한 주문이라도 주문완료 상태로는 변경이 불가능하도록 했습니다.

requestStatus(key) 의 value가 originStatus 이라면 주문상태를 변경하고, 아니라면 에러 처리합니다.