ERP 단위 설계: 기본 단위와 환산 비율
사출 원료를 25kg 포대로 사는 회사가 있다고 해 보겠습니다. 발주서에는 「10」이라고 적습니다. 입고할 때 창고 담당자도 「10」이라고 적습니다. 생산 실적에서 원료를 소요로 빼는 사람은 「12.5」라고 적습니다.
재고 화면의 합계는 이 숫자들을 그대로 더하고 뺍니다. 10 포대가 들어오고 12.5 kg 이 나갔는데, 화면에는 -2.5 가 남습니다.
단위는 수량 옆에 붙는 글자라는 생각
품목 테이블에 unit 칸 하나를 두고 「EA」, 「KG」, 「BOX」 같은 글자를 적는 설계가 흔합니다. 이 설계에서 단위는 화면에서 수량 뒤에 붙여 보여 주는 이름표입니다. 수량 칸의 숫자는 늘 그 단위라고 약속합니다.
이 약속은 한 품목을 한 가지 단위로만 다룰 때까지 지켜집니다. 앞의 원료처럼 사는 단위, 보관하는 단위, 쓰는 단위가 다른 순간 깨집니다. 문제는 깨졌다는 표시가 어디에도 나지 않는다는 것입니다. 숫자 칸은 10 과 12.5 를 똑같이 받아 줍니다.
단위를 글자로 자유 입력하게 두면 한 단계 더 나빠집니다. 「EA」, 「ea」, 「개」가 같은 뜻으로 섞이고, 단위별로 묶어 보는 집계가 갈라집니다. 이 부분은 공통 코드로 막을 수 있습니다. 코드로 막아도 앞의 -2.5 는 그대로 남습니다. 표기가 아니라 환산의 문제이기 때문입니다.
수량을 저장하는 단위는 하나
제가 보기에 출발점은 규칙 하나입니다. 재고 수량은 품목마다 정한 한 가지 단위로만 저장한다. 이것을 기본 단위, 또는 재고 단위라고 부릅니다.
원료라면 기본 단위를 kg 으로 둡니다. 포대로 발주하고 포대로 입고하더라도, 재고 이동으로 기록되는 수량은 kg 입니다. 10 포대 입고는 재고에 250 이 더해지고, 소요 12.5 는 12.5 가 빠집니다. 재고 합계는 237.5 kg 입니다.
사람이 포대로 말하는 것은 막지 않습니다. 발주서에는 10 포대라고 적히고 거래처에도 그렇게 나갑니다. 다만 그 숫자가 재고에 들어가는 순간 기본 단위로 바뀝니다.
환산 비율을 품목에 두는 이유
포대를 kg 으로 바꾸려면 「1 포대 = 25 kg」이 어딘가에 있어야 합니다. 이 비율은 단위의 성질이 아니라 품목의 성질입니다.
「BOX」라는 단위 자체에는 몇 개가 들었는지가 없습니다. 볼펜 한 상자는 12 자루이고 나사 한 상자는 1,000 개입니다. 같은 원료라도 공급처가 바뀌면 포대 크기가 20 kg 으로 달라질 수 있습니다. 그래서 환산 비율을 단위 표에 두면 곧 틀리게 됩니다.
저라면 품목에 기본 단위를 두고, 품목과 단위의 짝마다 환산 비율을 두겠습니다.
| 품목 | 단위 | 기본 단위로 |
|---|---|---|
| PP 원료 | 포대 | 25 kg |
| PP 원료 | kg | 1 kg |
| 볼펜 | BOX | 12 EA |
| 볼펜 | EA | 1 EA |
구매 단위가 하나뿐이라면 품목에 구매 단위와 구매 단위 환산 칸 두 개로 시작해도 됩니다. 같은 품목을 여러 단위로 사고팔기 시작하면 위처럼 별도 표로 옮깁니다.
거래 문서에 단위와 비율을 같이 남기는 이유
발주 줄에는 수량 10 만 적으면 안 됩니다. 어떤 단위로 10 인지, 그때 비율이 얼마였는지를 같이 적어야 합니다.
비율은 바뀝니다. 공급처가 포대를 20 kg 으로 바꿔서 품목의 환산 비율을 고쳤다고 해 보겠습니다. 지난달 발주 줄이 수량 10 과 단위 「포대」만 갖고 있다면, 그 발주를 다시 열었을 때 200 kg 으로 계산됩니다. 실제로 받은 것은 250 kg 이었습니다. 거래 문서는 그 거래가 일어난 때의 값을 박아 두어야 품목 설정이 바뀌어도 과거가 흔들리지 않습니다.
그래서 발주, 입고, 출하 같은 거래 줄에는 거래 단위, 거래 수량, 그때의 환산 비율을 저장하고, 재고 이동에는 기본 단위로 바꾼 수량을 저장합니다. 거래 줄만 보고도 재고에 얼마가 들어갔는지 다시 계산할 수 있습니다.
소수를 받는 단위와 받지 않는 단위
kg 을 기본 단위로 두면 수량 칸이 소수를 받아야 합니다. EA 로 관리하는 품목은 반대로 소수가 들어오면 안 됩니다. 볼펜 2.5 자루는 입력 실수입니다.
이 차이도 단위 쪽에 둘 수 있는 몇 안 되는 성질입니다. 단위마다 소수 허용 여부를 두고, 입력 검사가 그 값을 보게 하면 됩니다. 저장 칸은 소수를 받는 형식으로 통일하되, 부동소수점 오차가 합계에 쌓이지 않게 십진수를 그대로 저장하는 형식을 씁니다. PostgreSQL 이라면 numeric 입니다.
반대로 처음부터 수량 칸을 정수로 만들어 두면, kg 이나 m 로 관리하는 품목이 생기는 날 칸의 형식을 바꾸는 마이그레이션이 필요해집니다. 제조업을 대상으로 한다면 원료나 원단처럼 무게와 길이로 다루는 품목은 거의 피할 수 없다고 봅니다.
단위 설계를 미뤄도 되는 경우
모든 시스템이 이만큼 필요하지는 않습니다. 완제품만 개수로 사고파는 유통이라면 품목마다 단위 하나, 정수 수량으로 충분합니다.
제가 기준으로 삼는 질문은 하나입니다. 같은 품목을 사는 단위와 쓰는 단위가 다른가. 그렇다면 기본 단위와 환산 비율은 첫 설계에 들어가야 합니다. 재고 이동이 수천 건 쌓인 뒤에 섞인 단위를 풀어내는 일은, 어느 숫자가 어느 단위였는지 기록이 없어서 되돌리기 어렵습니다.
함께 읽기
- 문서 번호 참조와 외래 키: 되돌리기 코드를 번호로 짤 때의 문제제조업 ERP 데모에서 시드로 만든 「수금 완료」 매출 전표에서 수금 취소를 누르면 이상한 일이 생기는 구조를 찾았습니다. 원 전표는 미수로 돌아오는데 수금 전표는 지워지지 않고 남습니다. 수금 합계에는 받지 않은 돈이 이중으로 잡힙니다.
- 공통 코드와 기준정보(마스터 데이터) 구분하기공통 코드 표에 「설비 제조사」 그룹을 만들었다고 해 보겠습니다. 처음 몇 달은 잘 돌아갑니다. 설비를 등록할 때 제조사를 목록에서 고르고, 오타도 생기지 않습니다.
- ERP 전표 줄 설계와 분할 출하제조업 ERP 데모의 매출 전표 113장을 수주와 하나씩 대조했습니다. 전표 금액과 화면에 보이는 품목 줄의 합이 113장 모두 맞았습니다. 그런데 그 전표 테이블에는 품목 줄이 저장돼 있지 않았습니다.
- ON DELETE CASCADE 주의점: 세금계산서가 함께 삭제된 사례제조업 ERP 데모에 전자세금계산서 모의 발행을 붙인 날 저녁, 스키마를 다시 읽었습니다. 세금계산서 모델의 전표 연결 한 줄에 이런 주석이 붙어 있었습니다.
- ERP 공통 코드와 enum, 무엇으로 관리해야 할까?생산 실적 화면에 불량 사유를 적는 칸이 있다고 해 보겠습니다. 한 달이 지나 불량 사유별로 집계를 내면 이런 줄이 나옵니다.