요청서를 준비한 주문과 납품을 끝낸 주문을 둘 다 완료라고 부르면 다음 사람이 할 일이 사라진다. 절반만 납품하고 일부만 수금했다면 더 분명한 설명이 필요하다.
나는 공개 체험의 예외를 숫자 몇 개를 바꾸는 장식으로 두지 않았다. 남은 수량과 받을 금액, 다시 확인해야 할 상태가 서로 어떤 관계인지 코드로 분리했고 이번에는 그 경계를 깊게 풀었다.
먼저 단계와 결과를 서로 다른 값으로 보았다
상세 체험의 주문 J01은 견적·주문·요청서 준비·납품 확인·수금 확인의 다섯 단계를 거친다. 현재 단계와 수량, 시나리오가 입력 상태이고 납품량·매출 예시·수금·미수금은 거기서 계산한다. 화면의 글자만 완료로 바꾸고 금액을 따로 넣는 구조를 피한 이유는 단계와 결과가 서로 다른 이야기를 하지 않게 하기 위해서다.
이 예시의 금액은 납품 수량에 가상 단가 10만원을 곱한 설명용 값이며 세금과 회계 처리는 생략했다. 실제 회사의 매출 인식 기준으로 쓰겠다는 뜻이 아니다. 나는 예외가 생겨도 유지해야 하는 관계와 이번 체험이 다루지 않는 정책을 먼저 나눴다. 단순한 체험이 더 많은 업무를 처리하는 것처럼 보이지 않도록 경계를 남겼다.
부분 납품과 부분 수금은 남기는 것이 다르다
수량 6개로 부분 시나리오를 진행하면 납품 확인 단계에서 3개가 납품되고 3개가 남는다. 금액 예시는 30만원이다. 수금 확인 단계에서는 그 절반인 15만원이 수금되고 미수금 15만원이 남는다. 여기서 남은 납품 수량 3개와 미수금 15만원은 서로 다른 종류의 미완료다. 둘 중 하나만 보여 주면 다음 사람이 남은 일을 잘못 읽을 수 있다.
체험에서는 이 값을 같은 상태에서 파생해 함께 보여 준다. 현실의 일부 납품은 여러 날짜와 품목으로 나뉠 수 있고, 입금도 여러 전표에 배분될 수 있다. 이번 합성 모델은 그 장부 전체를 구현한 것이 아니다. 부분 완료를 설명할 때 남은 수량과 남은 돈을 각각 어떤 계산으로 만들었는지 공개하는 것이 이 예시의 역할이다.
반품 수량이 남은 납품에 다시 섞이지 않게 했다
반품 시나리오에서 6개 중 1개를 반품하면 순납품은 5개이고 금액은 50만원이다. 남은 납품 수량은 주문 수량에서 순납품과 반품을 함께 빼서 0이 된다. 반품한 1개를 자동으로 다시 보내야 할 수량으로 보지 않는 단순 정책이다. 이 선택을 숨기면 반품 후 남은 수량이 왜 0인지 이해할 수 없다.
수량 1개에서 1개를 반품하는 경계도 확인했다. 순납품과 금액은 0이고 반품은 1개이며 남은 납품도 0이다. 실제 업무에서는 교환 재출고나 환불, 반품 승인과 세금 문서가 필요할 수 있다. 그것들은 별도 정책과 전환으로 추가해야 한다. 이번 모델의 단순 반품을 모든 회사의 처리 방식으로 일반화하지 않는다.
취소한 상태를 다음 버튼으로 되살리지 않았다
취소 시나리오는 주문 단계부터 취소로 표시되고 다음 단계로 진행하지 않는다. 취소 안내가 나왔는데 뒤에서 납품량이나 수금이 늘면 화면은 서로 모순된다. 그래서 취소 여부를 파생 계산과 진행 조건에 함께 반영했다. 다음 단계 버튼만 비활성으로 꾸미는 것보다 모델도 같은 결정을 내리는 편이 검증하기 쉽다.
정상 수량 범위를 벗어난 입력도 진행하지 않는다. 현재 체험의 수량은 문자열로 보관하므로 빈칸이나 범위 밖 숫자를 정상 수량으로 바꾸지 않고 수정할 수 있게 남긴다. 취소와 입력 오류는 모두 진행을 멈추지만 이유와 다음 행동은 다르다. 처음부터 예시를 시작할지, 입력을 고칠지 구분할 수 있도록 안내를 따로 읽어야 한다.
수정했다면 이전 준비와 확인은 누구의 것인가
현재 체험은 수량이나 시나리오를 바꾸면 단계를 처음으로 돌린다. 이미 확인했던 금액이 수정 뒤에도 완료 상태로 남지 않게 한 단순한 경계다. 이번에는 이 판단을 더 명시적으로 재사용할 수 있도록 수정 번호를 가진 독립 모듈을 만들었다. 준비와 확인이 현재 수정 번호에 속할 때만 다음 행동을 허용한다.
예를 들어 수량 6개를 준비하고 확인한 뒤 7개로 고치면 수정 번호가 증가하고 두 확인 흔적은 비워진다. 같은 값 6개를 다시 넣는 것은 새 수정으로 세지 않는다. 이 모듈은 담당자의 실제 승인 서명이나 서버 기록을 대신하지 않는다. 화면에서 무엇을 다시 확인해야 하는지 드러내는 합성 상태 전환기로 공유한다.
코드와 구현 살펴보기
현재 체험의 수정 시 단계 초기화
export function editJourney(s,key,value){
if(key==='quantity'&&typeof value==='string')return {...s,quantity:value,phase:0};
if(key==='scenario'&&scenarios.includes(value))return {...s,scenario:value,phase:0};
throw Error('Unsupported synthetic edit');
}복구는 검증을 건너뛰는 통로가 되어서는 안 된다
새 모듈의 상태 복원은 정해진 형식 표시와 합성 자료 표시, 알려진 키, 안전한 수정 번호와 현재 번호에 맞는 확인 흔적을 검사한다. 오래된 확인 번호나 준비 없이 찍힌 확인은 받아들이지 않는다. 입력이 아직 틀린 초안은 그대로 복원할 수 있지만 준비 상태로 바꾸지는 않는다. 복원이 정상 상태를 임의로 만들어 내지 않게 한 것이다.
독립 테스트에서는 1~20의 모든 수량과 짧은 행동 조합 4320개를 거쳐 상태 규칙과 복원 결과를 대조했다. 한영 데모의 버튼 연결도 코드로 확인했지만 실제 기기 검수를 새로 수행한 것은 아니다. 아래 공유 모듈에는 구현과 테스트, 재사용 범위가 함께 있다. 실무로 확장할 때는 담당자 권한, 동시 수정, 서버 중복 요청, 취소 전표와 외부 발송을 각각의 책임으로 추가해야 한다.