#49スコア 4.5/5物流・倉庫

AI に出荷梱包を作らせてみた — 3つの画面が同じ2段スキャンを手組みしたので、ScanGate を作った(やってみた #49)

ルート: /shipping
デスクトップ表示
モバイル表示

375px のビューポートで撮影。縦長のページはフレーム内をスクロールします。

解説記事

AI に出荷梱包を作らせてみた — 3つの画面が同じ2段スキャンを手組みしたので、ScanGate を作った(やってみた #49)

⁠やってみたシリーズ⁠: 自作のデザインシステム @gunjo/ui群青)を、群青のことを一度も見たことのない AI に、実際の画面で組ませていく連載。物流/倉庫(WMS)3枚目——⁠出荷検品 / 梱包⁠(出荷照合 × カートン→商品の2段スキャン × カートン管理/重量 × 最終検品 × 配送ラベル)。

#47 ピッキング(取り出す)・#48 入庫(格納する)に続く出荷側。ピッキング済みを箱詰め前に照合し、⁠カートン(箱)をスキャンして開き → 商品をスキャンして詰める⁠——カートン→商品の2段スキャン。出荷の作法。

結果 — 4.5/5(tsc/build 緑・全コンポーネント採用)

tsc/build 緑・console 0・375px ハンディプライマリ・カートンスキャン→開封→商品スキャンで梱包+1・カートン未開封で商品スキャンは「先にカートンを」プロンプト・過剰梱包阻止・重量/配送業者ゲート・出荷確定で read-only サマリ。

※ 今回は予備知識ゼロの AI の最終レポートがセッションの制限で返らなかったが、退避した画面コードを検証して主要なシグナルを確認した(tsc/build 緑・全コンポーネント採用・scanStage の状態管理を26箇所で手組み)。

今回の本題 — 3画面が同じ2段スキャンを手組みした → ScanGate を作る

物流の3画面すべてが、⁠同じ2段スキャンのゲートを、scanStage の状態管理で手組み⁠していました。しかも⁠順序がバラバラ⁠なのに同じ形:

#47 ピッキング: location → item(棚を確認してから商品)
#48 入庫     : item → location(商品を読んで推奨棚へ・逆順)
#49 出荷梱包 : carton → item(箱を開いてから商品を詰める)

順序が3通り違っても、本質は同じ——⁠「スキャンして確定(引き継ぎ値)→ 次の段がその値を読んでスキャンしてカウント」⁠。毎回 scanStage/activeCartonId を手で書き、段ごとに ScanInputkey で remount し、自動フォーカスを配線していました。⁠3回ルール発火⁠ScanGate(#227)PR #232)を出荷:

<ScanGate
  stages={[
    { id: "carton", label: "① カートンをスキャン", onScan: (code) => {
        const c = openCarton(code)
        return c ? { ok: true, message: `${code} を開きました`, advance: "next", value: c }
                 : { ok: false, message: "見つかりません", advance: "stay" }
    }},
    { id: "item", label: "② 商品をスキャン", onScan: (code, ctx) => {
        const line = pack(code, ctx.values.carton)   // 前 stage の確定 context を読む
        return line ? { ok: true, message: `${line.name} を梱包`, advance: "stay" }
                    : { ok: false, message: "受注に無い商品", advance: "stay" }
    }},
  ]}
/>
  • 各段の onScan(code, ctx){ ok, message, advance, value } を返す。advance"next"/"stay"/"reset"/段の id)が状態遷移を駆動、value は段の id で記憶され、次の段が ctx.values[stageId] で読む。
  • 段の間で⁠自動で次へ進む+自動フォーカス⁠(スキャンガンのループ)。最終段の "next" は先頭に戻る+引き継ぎ値クリア=1サイクル完了。
  • 番号付きの ⁠ステップ表示⁠(done/active/todo)+命令的な ref ハンドル(reset/goTo/getValues)で「カートンを閉じる」「次のロケーションへ」ボタン。
  • 読み上げ・二重発火の抑制・履歴は ScanInput から引き継ぐ。

ブラウザ実証: カートン CTN-001 をスキャン→ carton→item に進む+引き継ぎ値を保存→商品スキャンで「デスクライト LED を CTN-001 に梱包(1/3)」(引き継いだカートンを参照)→ stay で連続梱包→「閉じる」ボタンの ref.reset() で 段1+引き継ぎ値クリア。

複利も全部効いた

ScanGate の土台 ScanInput はもちろん、DeltaEditableDataTableRevealSectionCheckbox(最終検品のチェックリスト)・Progresstone(前回 #48 で追加)⁠CardTitle as——⁠全部発掘・採用⁠。前々回・前回の投資が、出荷画面でも返ってきました。

学び — 「順序が違っても同じ形」は、合成コンポーネントのサイン

location→item / item→location / carton→item = 順序は違うが同じ2段ゲート
→ 抽象は「段の配列+各段の解決処理+確定した引き継ぎ値+自動で次へ」

3画面が⁠表面上は違う作法⁠(ピッキング/入庫/出荷)なのに、⁠同じ合成の構造⁠を手組みしていました。これこそ「上位でまとめるコンポーネント」が隠れているサイン——個別のつなぎのコードが3回、形を変えて再発したら、それは抽象を1つ作るべき合図です。ScanInput(単発スキャン)を3画面で作り切った上に、その⁠段階の組み立て⁠を ScanGate として括り出しました。コンポーネントは2層になりました。

次回予告(やってみた #50)

  • ⁠在庫ロケーション管理 / 棚卸移動⁠(容量 Meter#230 を2回目確認へ)。方針: 1業界3〜5枚・可能な限り違う内容・業界特有UI最優先。

試す

まだ alpha。3画面が同じ2段スキャンを手組みしたので、段階の組み立てを ScanGate として括り出した回。

この連載は、作者が AI(Claude と Codex)と協働で制作しています。実験・検証の設計、判断、公開前の事実確認は人間が行い、実作業と下書き執筆は AI が担っています。

使用した @gunjo/ui コンポーネント

この画面のソースが直接 import しているコンポーネントです。

cold AI が組み上げた実コード

ファイル名をクリックでソースを展開できます。

業界別「AI指示書パック」、先行登録を受付中です。