주문은 100건인데 정산은 98건이다 · 주문의 일생 · 실습
주문 100건의 흐름을 세어 보기
목표
주문 100건의 사건 기록에서 현재 상태를 직접 유도하고, 단계마다 몇 건이 남는지 세어 봅니다. 끝나면 "주문은 100건인데 정산 대상은 98건" 이라는 문장의 두 건이 어디서 어떤 이유로 빠졌는지 숫자로 말할 수 있습니다.
왜 중요한가
커머스 시스템에서 주문은 한 번에 끝나지 않습니다. 주문이 접수되고, 결제가 승인되고, 승인된 금액이 실제로 매입되고, 창고에서 출고되고, 배송이 끝나고, 구매가 확정됩니다. 여섯 사건은 서로 다른 시스템에서 서로 다른 시각에 일어나고, 각각 실패할 수 있습니다. 그래서 "주문 상태" 라는 컬럼 하나로는 어디까지 진행됐는지 말할 수 없습니다.
특히 승인과 매입은 다른 사건 입니다. 승인은 카드사에 "이 금액을 쓸 수 있느냐" 를 물어 한도를 잡아 두는 것이고, 매입은 "그 금액을 실제로 청구하겠다" 고 확정하는 것입니다. 승인만 나고 매입이 안 된 주문은 고객 카드에는 금액이 잡혀 있는데 우리 매출에는 없습니다. 정산 파일과 주문 건수가 어긋나는 가장 흔한 원인이 이것입니다.
되돌리는 방법도 단계마다 다릅니다. 매입 전이면 승인을 취소하면 그만이고, 매입 후 출고 전이면 매입을 취소해 환불해야 하고, 출고 뒤에는 물건을 회수해야 하고, 구매확정 뒤에는 판매자 동의 없이는 아무것도 못 합니다. 이 표를 모르면 "취소해 주세요" 라는 한 문장이 시스템에서 네 가지 다른 일이라는 것을 알 수 없습니다.
이 실습이 정한 값
실무에서는 아래 규칙이 회사의 주문 상태 정의서에 있습니다. 회사마다 다르므로 이 실습에서는 아래로 못 박습니다.
- 상태는 사건 집합에서 유도합니다. 위에서부터 훑어 처음 걸리는 것이 답입니다:
AUTH_FAIL→AUTH_FAILED,REFUNDED→REFUNDED,CONFIRMED→CONFIRMED,DELIVERED→DELIVERED,RELEASED→SHIPPING,CAPTURED→PAID,AUTH_OK→AUTHORIZED, 아무것도 없으면PLACED. - 되돌리기 수단:
AUTHORIZED는VOID(승인취소),PAID는REFUND(매입취소),SHIPPING은RECALL(배송 회수),DELIVERED는RETURN(반품),CONFIRMED는SELLER_ONLY(판매자 동의 필요),AUTH_FAILED와REFUNDED는NONE. - 정산 대상은
CAPTURED사건이 있는 주문뿐입니다. 승인만 난 주문은 매출이 아닙니다. - 배송비는 상품 합계가 50,000원 이상이면 0원, 아니면 3,000원입니다.
단계
1. 오른쪽 예시의 생성기를 /root/com/make_orders.py 로 저장하고 python3 make_orders.py 로 실행하세요. orders.csv(주문 100건), order_items.csv(품목 200줄), events.csv(사건 576줄)가 만들어집니다.
2. 주문마다 현재 상태를 유도해 /root/com/order_state.csv 에 order_id,state 머리글로 100줄 적으세요.
3. 단계별 건수를 /root/com/funnel.txt 에 orders=, authorized=, captured=, released=, delivered=, confirmed=, part_canceled=, refunded= 여덟 줄로 적으세요. 사건 줄이 아니라 주문을 셉니다.
4. 주문마다 지금 쓸 수 있는 되돌리기 수단을 /root/com/reversibility.csv 에 order_id,state,action 머리글로 적으세요.
5. 주문일과 매입일이 다른 주문을 /root/com/midnight.csv 에 order_id,ordered_at,captured_at 머리글로 적고, /root/com/midnight.txt 에 cross_day=, cross_amount= 두 줄을 적으세요. cross_amount 는 그 주문들의 order_amount 합계입니다.
6. 승인이 두 번 이상 기록된 주문을 /root/com/dup_auth.csv 에 order_id,auth_count 머리글로 적으세요.
7. /root/com/gap.txt 에 order_count=, captured_count=, count_gap=, order_amount_total=, captured_amount_total=, amount_gap=, gap_orders= 일곱 줄을 적으세요. gap_orders 는 매입까지 가지 못한 주문 번호를 쉼표로 이어 적습니다.
8. /root/com/lifecycle_report.md 에 ## 주문의 단계와 건수, ## 되돌릴 수 있는 자리, ## 날짜가 갈리는 자리, ## 시스템에 남겨야 할 것 네 절로 보고서를 쓰세요. 앞 단계에서 구한 숫자를 근거로 넣습니다.
참고
- 파이썬
csv모듈로 읽는 편이 빠릅니다. 사건은 주문별로set에 모아 두면 상태 판정이 한 줄로 끝납니다. - 흔한 실수 1: 사건 줄을 세는 것. 같은 주문에 승인이 두 번 있으면 승인 건수가 부풀어 오릅니다. 주문을 세세요.
- 흔한 실수 2: 날짜를
ordered_at하나로만 보는 것. 자정 직전에 들어온 주문은 매입이 다음 날로 넘어갑니다. - 흔한 실수 3: 마지막 사건 하나만 보고 상태를 정하는 것. 사건은 순서대로 들어오지 않을 수 있어서, 있는 사건의 집합으로 판정해야 안전합니다.
단계 8개
- 주문·품목·사건 데이터 만들기
- 사건에서 현재 상태를 유도하기
- 단계마다 몇 건이 남는지 세기
- 지금 되돌릴 수 있는 수단 정하기
- 주문일과 매입일이 갈린 주문 찾기
- 승인이 두 번 올라간 주문 찾기
- 건수와 금액 양쪽에서 벌어진 자리 재기
- 주문 흐름 점검 보고서 쓰기