入荷に追従する在庫 — 予定在庫への"先引当"と、入荷時の自動再配置
まだ届いていない在庫に注文を引き当て、入荷が確定したら引当を自動で組み替える。欠品と機会損失を減らす仕組み。
PREMISE予定在庫と実在庫という2つの層
通販/定期の在庫を扱う基幹エンジンでは、在庫を単一の数値として持たない。前提として在庫は2層に分かれる。ひとつは実在庫(入荷済ロット)で、すでに倉庫に受け入れ済みで即出荷できる数量。もうひとつは予定在庫(入荷予定ロット)で、発注済みだがまだ倉庫に届いていない、入荷予定日付きの数量である。
この分離があると、入荷を待たずに受注計画を前へ進められる。届く前の在庫にも注文を割り当てておけるからだ。以降で扱う「先引当」と「入荷時の再配置」は、いずれもこの2層構造を前提にした設計パターンとして説明する。
PRE-ALLOCATE予定在庫への"先引当"
定期便のように将来分の出荷が確定している業務では、入荷を待っていては出荷計画が組めない。そこで、まだ届いていない予定在庫(入荷予定ロット)に対して注文を"先引当"する。
- 入荷前でも受注を確定でき、出荷予定日を確約できる。
- 予定ロットごとに「どの注文がいくつ引き当てているか」を保持する。
- 引当の裏付けは受払(在庫の入出庫)台帳に記録し、後から復元できる状態にしておく。
ON-ARRIVAL入荷完了時に連動する2つの処理
予定ロットが実際に入荷完了すると、2つの処理が連動して走る。
- (A) 予定→実在庫へのシフト:受け入れた数量を、完了した予定ロットから実在庫ロットへ移す。ここで初めて「即出荷できる在庫」になる。
- (B) 予定→予定の引当再配置(リアロケート):完了した予定ロットに載っていた「引当済み」等を、他のまだ生きている予定ロットへ載せ替える。これにより既存注文の引当が失われない。
(A)だけを行うと、完了ロットに紐づいていた引当情報が宙に浮く。(B)を必ず対にすることで、注文と引当の対応が途切れない。
REALLOCATE再配置先の選び方(LIFO切り出し)
再配置は当てずっぽうに移すのではなく、受払台帳から復元した引当を規則的に切り出す。
- 受払(在庫の入出庫)台帳から、引当対象日ごとの残り引当数を復元する。
- 引当日を新しい順(LIFO)に、必要数だけ切り出して対象の予定ロットへ移す。
- 充当しきれなかった分は警告として可視化し、握りつぶさない。運用側が発注追加や納期調整で対処できるようにする。
GOAL目的とトレードオフ
この仕組みの目的は、入荷の遅延や数量変動が起きても注文が引当を失わないようにすることだ。完了ロットの引当を別ロットへ確実に載せ替えることで、欠品・過剰・引当漏れを防ぐ。
- 利点:入荷前から出荷計画が回り、機会損失を抑えられる。入荷のブレを注文に波及させない。
- トレードオフ:再配置ロジックは状態遷移が多く複雑になりやすい。また受払台帳が正確に整備されていることが大前提で、台帳が壊れると復元も再配置も破綻する。
def reallocate(done_lot, target_lots, ledger):
# 受払台帳から引当対象日ごとの残り引当数を復元
remaining = ledger.restore_remaining(done_lot) # {date: qty}
# 引当日を新しい順(LIFO)に並べる
for date in sorted(remaining.keys(), reverse=True):
need = remaining[date]
for lot in target_lots: # 生きている予定ロット
if need <= 0:
break
move = min(need, lot.free_capacity())
lot.attach(done_lot.allocations_of(date), move)
need -= move
if need > 0:
# 充当しきれない分は握りつぶさず警告に
warn(f"reallocation shortage: date={date}, qty={need}")
在庫を予定/実の2層で持ち、届く前の予定在庫にも先引当する。入荷完了時には「予定→実へのシフト」と「予定→予定の引当再配置」を対で走らせ、受払台帳から復元した残引当をLIFOで必要数だけ切り出して載せ替える。充当しきれない分は必ず警告に出す。台帳整備と再配置ロジックの複雑さと引き換えに、入荷のブレから注文の引当を守れる。