# 興国運輸（厚木事業所 配車管理）作業記録

**対象期間**: 2026-07-25 〜 2026-08-07
**対象**: `zsystem.jp/ellio/dispatchmng/`（事務所側）／`zsystem.jp/ellio/dispatch/`（現場側）
**作成日**: 2026-08-07

---

## 0. 概要

配車管理は 2 つの画面を **同じデータベース（`dispatch` / `carrierMaster` / `shippingschedule` / `arrivalschedule` / `customertable`）を共有する二画面構成** で運用している。

| 画面 | 場所 | 使う人 | 役割 |
|---|---|---|---|
| 配車管理（事務所側） | `ellio/dispatchmng/` | 厚木事業所 事務所 | 出荷予定PDFの取込、配車の割付、配車管理記録の閲覧・編集 |
| 現場打刻（現場側） | `ellio/dispatch/` | 興国運輸 積込担当 | タブレットでの受付・積込の時刻打刻、入荷受付 |

打刻は 5 段階で、記号 E〜I を内部キーとして使っている。

- **E** 指示時間（事務所が事前設定・現場はタップしない）
- **F** 受付（到着）／**G** 積込開始／**H** 積込完了／**I** 退場

本期間のコミットは 21 件。**うち 8/7 時点で本番未反映のものは無い**（末尾の付録に一覧）。

期間中の作業は大きく 5 本に分かれる。

1. 現場の**入荷受付フロー**を実用に耐える形へ作り込んだ（7/25〜8/7、6 コミット）
2. **配送先マスター**を新設し、走行距離・走行時間を実測値で投入して画面に載せた（7/27〜8/2）
3. 出荷予定PDFの取込を「**追加だけ**」から「**PDF を正とした同期**」へ作り替え、さらに**分納**に対応した（7/31）
4. 事務所→ドライバーの**連絡事項欄**を追加（7/31）
5. 表示の善悪判定の是正と、**編集権限・ログイン認証**の整備（8/7）

---

## 1. 現場の入荷受付フロー

期間を通して一番手を入れた領域。もともと現場画面は「事務所が作った配車行に対して時刻を打つ」だけだったが、**入荷（トラックが荷物を持って入って来る側）は事務所側に予定行が無いことがある**ため、現場が受付時にその場でレコードを起こす仕組みが要る。

### 1-1. 受付フローの3段構成（7/25 `ffc26c2` デプロイ済）

受付を **発送元 → 入荷予定の複数選択 → 車番** の 3 ステップに再構成した。

- 入荷予定（`arrivalschedule`）に `dispatch_id` / `car_no` / `carrier_company` / `carrier_driver` / `linked_at` を追加。打刻開始（F受付のINSERT）の時点で選択された予定行へ書き戻し、**同じ予定が二重に計上されるのを防ぐ**。既に紐付いている予定は上書きしない安全側の作り。複数選択したときは数量を合算し、備考に「混載」を入れる。
- 予定に無い商品を持ってきた場合のために `dispatch.has_unlisted_items` を追加し、カード・詳細に「予定外あり」バッジを出す。
- 車番入力欄に**最大積載kg**を追加。車両マスタ（`carrierMaster`）にヒットしても `max_load` が空なら入力を必須にし、入力値をマスタ側へ書き戻して補完する。
- 初回の F受付 INSERT でも**天候のスナップショット**を保存するようにし、既存の打刻経路と意味を揃えた。
- Android Chrome の URL バー分だけ画面下部が切れる問題への対策として、高さ指定を `100vh` から `100dvh`（フォールバックとして `100vh` を先に置く 2 段書き）へ変更。※実機確認は未実施（手元に Android が無いため CSS 変更のみ）。

### 1-2. ステップ順の入れ替え（7/26 `c1b48b5` デプロイ済）

現場の実運用に合わせ **車番 → 発送元 → 入荷商品** の順に入れ替えた。車番を最初に取ると、その時点で会社・ドライバー・最大積載が確定するため、以降のステップが軽くなる。

- 「戻る」で車番入力に返ったときに入力を失わないよう、車番が空のときだけ DOM を初期化する作りにした。
- 予定の無い発送元を選んだ場合は入荷商品の選択ステップを自動的に飛ばす。
- ボタンの文言を状況に応じて出し分け（`打刻開始 ›` / `選択せずに進む ›`）。
- サーバー側の入出力仕様は変更なし。

### 1-3. 受付カードが透ける不具合（7/27 `6006adf` ※単独のデプロイ記録は無いが、8/7 の同一ファイル転送で本番反映済み）

入荷受付カードの背景がグラデーション 1 層で右側が透明だったため、画面上部に固定表示している間、裏を配車カードがスクロールすると透けて見えていた。不透明な背景色を重ねて塞ぎ、影を付けて浮いて見えるようにした。

### 1-4. 同一車番に複数の実車がある場合の選択ダイアログ（8/7 `e481c05` デプロイ済）

**背景**: 車両マスタには**同じ車番が別会社・別実車で登録されていることがある**。実測（8/7時点）では車番 `2637` が

- 岡田運輸 / 生井 満 / 4t平車 相模130あ2637 / 3,150kg
- 山本運送 / 大橋 / 29,400kg

の 2 台。従来の検索は先頭 1 件しか返しておらず、現場が車番を打つと常に片方が採用され、もう一方を選ぶ手段が無かった。

**実害（本作業で発見・修正済）**: 8/6 の入荷 1 件（`dispatch` id976・ＴＳＣ・山本運送）は、打刻した 12:21 の時点で山本運送のマスタ行がまだ存在せず（作成は同日 14:06）、岡田運輸の 3,150kg が実績行に焼き付いていた。会社名とドライバーは後から手直しされたが最大積載は編集対象外だったため 3,150 のまま残り、**積載率が 796.1% と表示されていた**。`UPDATE dispatch SET max_load=29400 WHERE id=976` で修正（正しくは 85.3%）。
※出荷便は最大積載を実績行に持たず表示時に毎回マスタを引き直すため、この焼き付きは入荷でしか起きない（出荷側 132 便に誤りが無いことを確認済み）。

**実装**:
- 車番検索の `LIMIT 1` を撤去し、有効な候補を全件返す。0件／1件／N件で戻り値の形を変え、複数時もトップレベルは先頭候補で埋めて**旧クライアントとの互換を保つ**。
- 2 件以上なら現場に**会社名（大きく）＋ドライバー氏名**で選ばせるダイアログを出す。車格・ナンバー・最大積載は補助情報。タブレット運用のため決定ボタンは置かず 1 タップで確定。
- 受付レコード作成 API が選択された行の ID を受け取るようにした。これが無いと表示順の先頭が採られ、**選ばれていない側の最大積載を書き換えてしまう**。
- 候補が複数ある間は未選択のまま次へ進めない（× で閉じても進ませない）。車番を打ち直したら前回の確定内容を破棄する。

対象は入荷の車番入力ステップのみ。再編集ダイアログは会社名・ドライバーが自由入力でマスタ照合していないため今回は対象外。

### 1-5. 「これではない（別の会社）」導線と手入力時のマスタ登録バグ（8/7 `41037c9` デプロイ済）

1-4 の続き。**車番を打って他社のトラックがヒットした場合に「それは違う」と言う手段が画面に無かった**。唯一の逃げ道は不特定業者用の「その他（会社名手入力）」ボタンで、ヒット結果を否定する導線には見えない。

さらにサーバー側に実害のあるバグがあった。手入力モードでも車番だけでマスタを引き直していたため、

- (a) 「配送マスタに追加する」のチェックが**黙って無視され**、新しい会社がマスタに登録されない
- (b) ヒットした**他社行の最大積載を現場入力値で上書きする**

8/6 の 2637 はまさにこの状況で、現場は別会社として登録できず、いったん岡田運輸で通してから事後修正していた（最大積載は 3,150 のまま残った）。1-4 の事故の真因はここにある。

**実装**:
- 補完カードと選択ダイアログの両方に「これではない（別の会社）」「一覧にない（別の会社）」を追加し、**車番を保ったまま手入力モードへ入れる**ようにした。
- クライアントから `manual_mode=1` を送り、サーバー側はこのとき車番によるマスタ引き直しを行わない。これで (a)(b) が同時に解消する。
- 同一（会社名・車番）の行が既にある場合は重複 INSERT せず、その行の最大積載が未登録なら今回の入力で補完する。ヒット時と挙動を揃えた。

※**本番DBを汚さないため、手入力モードでの実登録（実際の `dispatch` 行と `carrierMaster` 行の作成）は未実施**。構文チェックと画面表示までの確認に留めている。実機で 1 件通して確認が必要。

---

## 2. 配送先マスターの新設と走行km

> このセクションはコミット上 `ellio:` の接頭辞で入っているが、目的は **配車管理記録に「走行km」列を出すこと**なので、配車管理の作業として記載する。

### 2-1. 配送先マスターの新設（7/27 `3295a30`）

配送管理の納入先はこれまで `dispatch.content` の**自由入力**で、マスターが存在しなかった。発送元（`type='発送元'`）と並列に `type='納入先'` として `customertable` に新設。

- 出荷ステータスの `dispatch.content` から重複を除いて種を作り、コード付 34 件＋コード無 2 件＝**36 件**を投入。
- 「㈱ＤＮＰエリオ　大阪工場」のような全角・空白の表記ゆれは 1 件へ名寄せ。
- 文字コードは HEX で既存カラムを確認し raw UTF-8 と判定してから接続文字コードを決めた（過去にコメントが二重エンコードで化けた事故があるため、この確認は必須手順にしている）。
- ALTER・実 INSERT・ロールバック用 DELETE を `ellio/dispatch/customertable_destination.sql` に保存（再現・監査用）。

### 2-2. 走行距離・走行時間の算出と投入（7/27 `1be48d5` `93d96e0` `2a9d6eb` `ad6c39a`）

拠点（DNPエリオ愛川：神奈川県愛甲郡愛川町中津4013）から各納入先までの**片道の道路走行距離・所要時間**を算出して投入した。

- 列: `driving_distance_km` DECIMAL(6,1)／`driving_time_min` INT。単位を列名に埋めて誤読を防いだ。緯度経度は既存列を使用。
- 手順: 住所調査 → **国土地理院ジオコーダで座標化** → **OSRM で道路距離（driving）を計算**。
  ※当初 Nominatim（OpenStreetMap）を使ったが日本の住所・郵便番号の精度が低く誤りが多発した（府中が岡山になる等）ため、国土地理院に切り替えて解決。
- **再ベース（7/27 `ad6c39a`）**: 途中で `shippingschedule.nonyusaki_addr` に**納入先の公式住所**が入っていることが分かったため、コード付 34 件をこれを正として全面照合し、座標・距離・時間を再計算した。多くは ±0.1km の差だったが、意味のある差もあった。
  - 原田港湾（海岸通 → 山下町279-1 5号上屋）35.6 → 37.5km
  - イトーキ関東第2（番地2288が判明）106.5 → 108.8km
  - 三菱電機静岡 146.7 → 145.3km
  - 岩谷鋼業（コードの郵便番号と実在確認が食い違い保留にしていた）→ 住所判明で**保留解除 436.8km / 325分**
- 住所比定の**確度（高／中／低）**を `sourceField` に記録。最終的に 36 件すべてに距離が入り、確度は高 35 / 中 1。
- 距離幅は 0.0km（拠点と同一＝DNPエリオ東京工場）〜 770.6km（三和広島／安芸高田）。

### 2-3. 配車管理記録に「走行km」列を追加（7/27 `285b9ee` `b9b29d4` `ac62cb3` デプロイ済）

積載率の右に列を追加（全 21 列）。**表示専用で DB へは書かない**。

- 突合は「記録行の `content` から `(コード)` を正規表現で抜き、**コード優先**、無ければ名称完全一致、それも無ければ `—`」。
- 表示の丸めは 2 度調整した。当初は小数第1位 → 四捨五入して整数 → 最終的に **1km超は整数・1km以下は小数第1位**（0.6km の DNPエリオ東京工場が 0 や 1 に潰れるのを避けるため）。DB 値は DECIMAL(6,1) のまま。
- 実データ突合: 出荷 35 件ヒット／入荷 5 件は `—`（入荷は発送元なので納入先マスターに無い）。

### 2-4. 納入先マスター管理画面と入力補完（7/29 `99516d4` デプロイ済）

- **入力補完**: 新規／編集ダイアログの納入先欄を候補リスト化。値は `名称(コード)` 形式で `dispatch.content` と互換にし、走行km の突合が効くようにした。未登録の名称を入力したときは確認のうえマスターへ追加する。
- **マスター管理画面**: ツールバーに「納入先マスター」ボタンを追加し、名称／コード／住所／走行km／走行分をインライン編集・追加・削除できるようにした。全操作を `type='納入先'` のスコープに閉じ、発送元や他の行に干渉しない。
- **距離の自動再計算はこの画面には載せていない**。本番サーバーの PHP（CLI 5.3）では TLS 1.2 が使えず、国土地理院・OSRM へ接続できないため。住所を編集した後の距離は手入力するか、作業端末側で一括再計算する運用。

### 2-5. 1事業所が複数の種別を持つケースへの対応（8/2 `f7b8d1c` デプロイ済）

**1 つの事業所が「納入先」であると同時に「ユーザー」でもある**ケースがある（例: 三菱電機(株)静岡製作所 = customerCode 007276 / delivercode 422802101）。`customertable` を 1 事業所 1 行にまとめるため、種別を**カンマ区切りの複数値**にした。

- 種別の等値比較 9 箇所を `FIND_IN_SET(...)` に置換（読み取り 5・更新/削除のガード 2・現場側 2）。INSERT は単一値を入れるだけなので変更なし。列は varchar(255) で桁は十分のため DDL 変更なし。
- **★ガードを等値のままにすると危険**: 条件不一致でもエラーにならず 0 行更新になり、画面上は成功に見えて何も起きないという、最も気づきにくい壊れ方をする。
- **★`FIND_IN_SET` は空白を含めて完全一致で判定する**ため、値の間に空白を入れてはいけない（`ユーザー, 納入先` は判定できない）。
- 検証: 旧コードと新コードを同一DB・同一時刻で実行し 6 エンドポイントがバイト一致。書き込み系 9 項目と本番HTTP経由 7 エンドポイントを確認。本番データは完全復元。

---

## 3. 出荷予定PDF取込を「PDF基準の同期」へ

### 3-1. 追加のみ → 集合演算による同期（7/31 `829e066` デプロイ済）

**症状**: 毎日 7 日分の PDF を取り込む運用で、出荷が前倒しになっても（例: 7/29 の㈱原伸梱包物流 → 7/28）**旧日付の予定が残留する**。

**原因は 3 つ**:
1. **主犯**: 既存の受注番号は「NULL・空欄のときだけ補完する」作りで、**日付や数量が変わっても更新されなかった**。元は「事務所の手動編集を守る」意図。
2. 配車行のグループキーが（納期日, 納入先）なのに、画面は**出荷日**でグルーピングしていた。出荷日だけ動くと画面に反映されず、納期も動くと新キーで INSERT されて旧行が孤児になる。
3. **PDF から消えた予定を落とす処理が存在しなかった**。

**設計**: 受注番号（`orderno`）を唯一の同定キーにする。受注番号は PDF にも載るため、移動／消滅を**推測ではなく集合演算で確定できる**。

- 同期スコープ＝**PDF に登場した出荷日の最小〜最大**。
- 出荷予定を真の UPSERT に（日付・数量・重量・規格を上書き）。工場備考だけは PDF が空なら既存を残す。
- スコープ内で PDF に無い受注番号を削除。
- 旧グループと新グループの受注番号の**重なり**があれば「移動」、無ければ「消滅」。移動時は備考・連絡事項・業者・車番・氏名・電話を引き継ぎ、**打刻（E〜I）はクリア**。移動先に既存行がある場合は**空欄のみ転記して統合**する（移動先の入力を壊さない）。

**削除してよい行の判別**が肝で、取込バッチ番号が 3 値で機能する。

| 値 | 意味 | 削除対象 |
|---|---|---|
| 14桁の数字 | PDF取込 | ○ |
| 空文字 | 手入力（新規登録） | ✗ 保護 |
| `arrival-tap` | 現場入荷（現場画面から） | ✗ 保護 |

ステータスが「出荷」であることも併用する（バッチ番号だけでは入荷行も非空なので不十分）。

**安全装置**:
- 2 段階操作。まず対象一覧を提示し、確認して初めて実行する。
- **サーバー側にも確認フラグのガードを置いた**。これが無いと、旧い画面を開いたままのタブが確認なしで破壊的な同期を実行してしまう（旧 JS は取込モードだけを投げるため）。
- 削除・移動・要確認（打刻済み）の一覧を実行の前後どちらにも表示。
- 処理全体を 1 トランザクション（両テーブルとも InnoDB）。

**テスト**: 本番DBしか無いため、未来日の窓（8/5〜8/6）を JSON に控えて実行 → 検証 → 厳密復元（列単位で差分 0 を確認）。冪等性・前倒し（統合／単独）・消滅・新規・手入力行と現場入荷行の保護・確認ガード・本番 PHP 5.6 でのドライランまで確認した。

### 3-2. 分納への対応（7/31 `6726327` デプロイ済）

**発見**: 出荷予定は**同一の受注が複数の出荷日に分かれる「分納」が常態**だった。7/6 版の工程会議資料 96 行中 **20 行（21%）が分納**で、取込済みの 18 行は**全件が 1 回分の数量しか保持していなかった**（数量が分納 1 便目と完全一致）。裏付けとして、出荷予定と受注データの突合 349 行のうち **78 行で 出荷数 < 指示枚数**、比率も 400/2000・200/600・180/540 と分納らしい分数だった。
例: `38095355-01-01` は資料上 `7/21(200)、7/27(200)、8/3(200)` だが DB には 7/21 の 200 のみ。

**原因は 2 箇所。DB の一意制約に到達する前に、パース段階で既に潰していた**。
- 取込処理で受注番号をキーに代入していたため、分納 2 行のうち**後勝ち**で 1 行に潰れていた。
- 既存行の照合表を**全件**から作っていたため、スコープ外の既存行まで更新分岐に入り出荷日を上書きしていた。同じ関数の削除・移動ステップはスコープ内限定だったのに、この 1 ステップだけが不整合だった。

**分納と予定変更の判別**（1 回の貼り付けは最大 4 日分の出荷日を含む）:

| 条件 | 判定 |
|---|---|
| 同一PDF内に同じ受注番号が別々の出荷日で出現 | **分納で確定**（同時に 2 日を指示＝変更ではありえない） |
| 既存行の出荷日がスコープ内 かつ PDFに無い | **移動 or 取消で確定**。その行を落とす |
| 既存行の出荷日がスコープ外 | 触らない（その PDF はその日を扱っていない） |

**変更内容**:
- 一意制約を `(orderno)` から **`(orderno, dispatch_date)`** へ変更（受注番号単独の索引は別途保持）。
- 取込側の同定キーも「受注番号｜出荷日」に。**受注番号で引くための別マップを併設した**。ここを再キーするだけだと、配車便の移動先判定が全ての旧グループを削除対象に落とし、**打刻ごと消える**。分納は複数の行き先に投票させる形にした。
- 削除を受注番号指定から **ID 指定へ**（受注番号指定だとスコープ外の分納を巻き添えにする）。
- **出荷日が読めない明細は取り込まない**（日付 NULL は一意制約の穴になるため）。件数は別途返して見えるようにした。
- ドライランの件数集計も同じ単位に揃え、分納で増える行数を追加表示。

**★ALTER とコードのデプロイは必ず同時**。ALTER 先行＝重複を防ぐものが無い期間ができる。コード先行＝分納 2 件目の INSERT が旧一意制約に弾かれ、**取込トランザクション全体がロールバックして取込が全面停止する**。

**検証（本番データを 1 バイトも変えていない）**:
1. 事前チェック: 重複 0 件／出荷日 NULL 0 件
2. バックアップ: テーブルコピー ＋ mysqldump をローカル回収（`shippingschedule_bk20260731_2101` / `dispatch_bk20260731_2101`）
3. ALTER
4. **COMMIT を ROLLBACK に差し替えたコードで本番に実書き込みを走らせ**、前後スナップショット（全行の全列値）が完全一致することを確認 → 書き込み経路を無害にテストできる
5. デプロイ後、読み取り系 10 エンドポイントを**旧コードと新コードで同一時刻・同一DBに対して実行**しバイト一致を確認（md5 比較だけだと他者のデータ更新と区別できない）

結果: 分納による追加 2 件・削除 1 件、配車行の削除・移動は 0、データ変更 0。

---

## 4. ドライバー連絡事項（7/31 `890d7e2` デプロイ済）

**なぜ**: 事務所からドライバーへ「ゲート№3から入場」「8:30に電話」等を伝える欄が無かった。納入先行（納入先名と荷重量の間）に、便行の備考と同じ直接入力欄を置きたいという要望。

- DB: `dispatch.driver_note VARCHAR(200)`。**粒度は納入先グループ（出荷日, 納入先）単位**で、既存の特記事項と同様、グループ内の全便に同じ値を書く（テーブル自体は便単位なので非正規化）。
- 文字コードは既存の備考類と同じ raw UTF-8（HEX で確認済み）。
- 表示はグループ内の**空でない先頭値**を採用する（先頭の便が空でも消えないように）。
- **便を追加する処理で連絡事項を引き継ぐこと**。引き継がないと現場画面は行単位で読むため「便を追加した便を選んだドライバーだけ連絡が出ない」という分かりにくい欠落になる。
- 30 秒ポーリングの差分取得にも項目を追加し、事務所の入力が現場へ自動反映される。
- 現場画面側は**読み取り専用表示**。カード一覧は「連絡」チップ、詳細は「連絡事項」バッジ。特記事項とはオレンジ系で色分け。
- CSS: 納入先行のグリッドを 7 列→8 列に（列数と子要素数は必ず一致させる）。
- 副産物として、現場画面の詳細ペインを grid から縦 flex に変更。備考帯が 1 つでも出ると余白がそこに吸われて間延びしていた既存の崩れも解消した。

---

## 5. 表示の是正と権限整備

### 5-1. 車番手入力時の車両マスタ自動補完（7/26 `77c798d` ※単独のデプロイ記録は無いが、8/7 の同一ファイル転送で本番反映済み）

事務所側の便編集ダイアログで車番を手入力したとき、車両マスタを車番完全一致で検索し、**1 件だけ一致したら**会社名と最大積載を自動セットする。0 件・複数件のときは最大積載表示を伏せて自動補完しない。6 シナリオ（一意／積載0／重複／未登録／空クリア／会社名既入力の上書き）で単体テスト済み。

### 5-2. 入荷カードの積載判定を出荷から分離（8/7 `d0e41bb` デプロイ済）

**背景1（善悪の逆転）**: 納入先カード右の判定バッジは出荷用だったが、入荷カードにもそのまま流用されていた。

- **出荷** = これから積む。手配した車の積載量が荷重に足りているか（足りない＝不足＝警告）
- **入荷** = すでに積んで来ている。荷重が積載量を超えていたら**過積載（法令違反）**

向きが逆なので、**入荷で過積載の便が緑の「充足」と表示されていた**。実例: 8/7 山信物流／好本達也（車番111）最大積載 3,150kg に対し荷重 3,242kg。修正後は赤字「過積載」。

**背景2（警告だけ目立たせる）**: 7/1〜8/7 のカード 123 枚のうち **97 枚が「充足」で埋まっており**、その中から異常を探す形になっていた。正常時は無表示にし、対処が要るものだけ色付きで出す方針に変更。

**実装**: 入荷と出荷で判定を分岐。入荷は「過積載（赤）／積載量未登録／荷重未入力」のみラベル表示。語も「手配」→「最大積載」に変更（「手配」はこれから車を割り当てる出荷側の語で、到着済みの車には合わない）。出荷の「充足」も無表示化し、「不足 Nkg」「未割当」は残した。

**結果**: 123 枚中、色付きで出るのは過積載 1 件・未割当 1 件のみ（他は荷重未入力 7 件）。
※便行の「積載率」は元から 100% 以上で赤くなる実装で入荷でも正しい向きのため未変更。

### 5-3. 配車管理記録のセル編集とログインチェック（8/7 `6102c57` デプロイ済）

**目的**: 21 列のフラットな記録表の項目を、できる限り画面上で直せるようにする。

**編集可否の切り分け（ユーザーと合意）**:

| | 列 |
|---|---|
| **編集可（15列）** | 会社名／氏名／車番／E指示受付／F受付到着／G積込開始／H積込完了／I退場／状況／内容(納入先)／梱包数／重量kg／最大積載／天候／備考 |
| **編集不可（6列）** | 日付（グループ移動が起きるため禁止）／滞在分・荷待分・荷役分・積載率（計算値）／走行km（配送先マスター由来。1行直すと同一納入先の全便に波及するため画面では直せない） |

**最大積載の方針**: 実績行の `max_load` に書く（＝この便の実績を直す）。車両マスタは触らない。結果としてその便は以後マスタを直しても追従しなくなる（意図どおり）。

**天候の方針**: 実装を確認したところ、打刻時点の選択値をその行だけに書く実装で、「1日1回入力・その日の全レコードに一括反映」というスキーマのコメントが実態と食い違っていた。**実装が正しいのでコメント側を修正**（データ型・値は不変）。

**実装**:
- 管理者判定を画面へ注入し、編集可能セルだけに編集用の属性を付与する（**非管理者には属性ごと出さない**）。
- ダブルクリックで入力欄化 → Enter/フォーカス外れで保存・Esc で取消。保存後は記録を引き直す（滞在分・積載率など算出値の整合を保つため）。リスナは表全体に 1 つの委譲。
- **画面で dblclick を殺すだけでなく、更新 API 側にも権限チェックを置いた**（POST を直接叩けるため）。
- 梱包数・重量・最大積載は整数キャスト＋カンマ除去（文字列のまま UPDATE すると MySQL 側で黙って 0 に丸められる）。値の妥当性検証は入れない＝内容の責任は編集者にある運用。
- 「ダブルクリックで編集が可能です」のヒントバッジを管理者にのみ表示。

**ログインチェック**:
- 事務所側にログインチェックを追加。**switch より前に置き、AJAX の各モードも保護する**（画面だけ塞いでも更新モードを直接叩けてしまうため）。
- **★現場打刻側には意図的に掛けない判断をした**。ログインチェックはリファラが自ドメインのときしかクッキーでのログインを認めず、さらにクッキー寿命が 8 時間しかない。現場タブレットはブックマーク／ホーム画面から直接開くため、**朝イチの打刻が止まる**。将来「認証漏れ」と誤解されないよう、コードの冒頭にその旨のコメントを残した。

**動作確認**: 管理者でヒント表示あり、非管理者で編集属性なし、非管理者の直 POST → 「権限がありません」、許可外フィールド → 拒否、数値に `"3,150"` → 3150 で保存。ブラウザでの実操作もデプロイ前にユーザーが確認済み。

---

## 6. 未解決事項・既知の挙動

作業中に発生した事故と、仕様上そうなることが分かっている挙動をまとめる。

### 6-1. 本番データに残っている影響

| 内容 | 状態 |
|---|---|
| `dispatch` id977 に API 疎通確認で実書き込みをした（8/7） | 最大積載は 0 に戻したが、**天候に書いた「晴」は元値が復元できていない**。同日の他行から推定して晴の可能性が高い |
| `dispatch` id976 の積載率 796.1%（8/6 入荷） | `max_load=29400` へ修正済み（正しくは 85.3%）。原因は 1-4／1-5 で修正済み |
| **既に上書きで失われた過去の分納** | **復元されない**。今後の取込から積まれるのみ |

### 6-2. 未実施の確認

- **手入力モードでの実登録が未検証**（8/7 `41037c9`）。本番DBを汚さないため、構文チェックと画面表示までに留めている。**実機で 1 件通して確認すること**。
- **Android 実機での画面下部の切れ（`100dvh` 対応）が未確認**（7/25 `ffc26c2`）。手元に Android 端末が無いため CSS 変更のみで対応した。

### 6-3. 仕様上の既知の挙動

- **後ろ倒しで PDF の期間外へ出た予定は「移動」でなく「削除」になる**。翌日以降の PDF で新規として復活するが、**配車情報・備考は失われる**。範囲全体を削除する方針の裏返し。
- **`wait_time`（荷待分）／`work_time`（荷役分）は誰にも書かれておらず常に 0**。今回は現状のまま。
- 記録側の「㈱ＤＮＰエリオ　大阪工場」（全角表記）はマスター名寄せ後の名称と一致せず、走行km が `—` になる（コード無しゆえの取りこぼし・許容）。
- 距離の自動再計算は納入先マスター画面に載せていない（本番 PHP 5.3 が TLS 1.2 非対応のため外部 API へ接続できない）。住所編集後は手入力するか作業端末で一括再計算する。

### 6-4. 積み残しの設計課題

- 再編集ダイアログは会社名・ドライバーが自由入力で車両マスタと照合していない。1-4 のダイアログは受付ステップにしか入っていない。
- 出荷側の「不足時に補填候補の車種を提案する」構想（Phase 3 の設計メモ）は未着手。

---

## 7. 検証手法（再利用可能なもの）

期間中に確立した、**本番DBしか無い環境で安全に検証する**ための手順。

1. **COMMIT を ROLLBACK に差し替えて本番に実走させる** — 書き込み経路を実データで通しつつ、前後スナップショット（全行の全列値）の完全一致を確認する。書き込みロジックを無害にテストできる。
2. **新旧コードの同時実行によるバイト比較** — 読み取り系エンドポイントを旧コードと新コードで**同一時刻・同一DB**に対して実行して比較する。md5 の突き合わせだけでは他者のデータ更新と区別できない。
3. **未来日の窓を控えて実行 → 厳密復元** — 影響が及ぶ範囲を JSON に控えてから実行し、検証後に列単位で差分 0 を確認して戻す。
4. **文字コードは書き込み前に HEX で既存カラムを判定してから経路を決める** — この環境は raw UTF-8 と二重エンコードの 2 経路が混在しているため。
5. **ローカル `php -S` で本番DB直結** — zsystem.jp のルートで起動すると全画面が動く。ただし書き込みは本番データなのでテスト後に必ず戻すこと。またログインチェックのリファラ判定により `127.0.0.1` 直打ちでは入れないため、メニューからリンクで遷移する。

---

## 付録: コミット一覧（2026-07-25 〜 2026-08-07）

| # | 日時 | ハッシュ | 件名 |
|---|---|---|---|
| 1 | 07-25 22:10 | `ffc26c2` | ellio/dispatch: 入荷受付フロー刷新＋Android URLバー対策 |
| 2 | 07-26 20:55 | `c1b48b5` | ellio/dispatch: 入荷受付フローを 車番→発送元→入荷商品 順に入替 |
| 3 | 07-26 23:18 | `77c798d` | ellio/dispatchmng: 便編集ダイアログの車番手入力で carrierMaster 自動補完 |
| 4 | 07-27 14:06 | `3295a30` | ellio: 配送先(納入先)マスターを customertable に新設・投入（Phase A） |
| 5 | 07-27 14:26 | `1be48d5` | ellio: customertable に走行距離カラム driving_distance_km を追加 |
| 6 | 07-27 15:02 | `93d96e0` | ellio: 配送先の走行距離/座標/住所を投入（GSI+OSRM, 35件） |
| 7 | 07-27 15:04 | `2a9d6eb` | ellio: customertable に走行時間(driving_time_min)追加＋確度を投入 |
| 8 | 07-27 15:21 | `285b9ee` | ellio/dispatchmng: 配車管理記録に走行km列を追加 |
| 9 | 07-27 15:23 | `b9b29d4` | ellio/dispatchmng: 走行kmを四捨五入・整数表示に変更 |
| 10 | 07-27 15:38 | `ad6c39a` | ellio: 配送先マスターを shippingschedule 公式住所と照合・再ベース（34件） |
| 11 | 07-27 15:46 | `ac62cb3` | ellio/dispatchmng: 走行km、1km以下は小数点1桁表示に変更 |
| 12 | 07-27 22:01 | `6006adf` | ellio/dispatch: 入荷受付カードを不透明化 |
| 13 | 07-29 14:50 | `99516d4` | ellio/dispatchmng: 納入先マスター管理画面を追加＋納入先入力の補完（Phase B） |
| 14 | 07-31 12:35 | `890d7e2` | ellio/dispatchmng: 納入先行にドライバー連絡事項欄を追加 |
| 15 | 07-31 14:19 | `829e066` | ellio/dispatchmng: 出荷予定PDF取込をPDF基準の同期に変更 |
| 16 | 07-31 21:05 | `6726327` | dispatchmng: 出荷予定の分納対応（UNIQUEを orderno+dispatch_date へ）※ |
| 17 | 08-02 01:25 | `f7b8d1c` | dispatchmng/dispatch: customertable.type をカンマ区切り複数値に対応 |
| 18 | 08-07 13:23 | `e481c05` | ellio/dispatch: 同一車番に複数実車がある場合の選択ダイアログを追加 |
| 19 | 08-07 13:50 | `d0e41bb` | ellio/dispatchmng: 入荷カードの積載判定を分離し過積載を赤表示 |
| 20 | 08-07 14:17 | `41037c9` | ellio/dispatch: 「これではない（別の会社）」導線を追加＋手入力時のマスタ登録バグ修正 |
| 21 | 08-07 15:18 | `6102c57` | ellio/dispatchmng: 配車管理記録のセル編集（管理者のみ）とログインチェック追加 |

※ 16 は別プロジェクト（shearplan の設計メモ）を同梱しているが、本記録では dispatchmng 分のみを扱っている。

### 期間中に追加された DB スキーマ変更ファイル

| ファイル | 内容 |
|---|---|
| `dispatchmng/alter_add_driver_note.sql` | `dispatch.driver_note VARCHAR(200)` 追加 |
| `dispatchmng/alter_shippingschedule_unique.sql` | 一意キーを `(orderno, dispatch_date)` へ変更 |
| `dispatchmng/alter_weather_comment.sql` | 天候カラムのコメントを実装に合わせて修正（型・値は不変） |
| `dispatch/customertable_destination.sql` | 配送先マスターの ALTER・実INSERT・UPDATE・ロールバック用DELETE |

※ 7/25 `ffc26c2` の `arrivalschedule`（`dispatch_id` / `car_no` / `carrier_company` / `carrier_driver` / `linked_at`）と `dispatch.has_unlisted_items` の追加は、**スクリプトを残さず本番DBへ直接適用している**。この期間を再現・復元する場合はこの 6 列が漏れるので注意。

### バックアップ

| 名称 | 取得日 |
|---|---|
| `ellio.shippingschedule_bk20260731_2101` / `ellio.dispatch_bk20260731_2101` | 07-31（分納対応の ALTER 前） |
| `dispatchmng/_backup_dispatch_ss_20260731_1240.sql` | 07-31（PDF同期化の前） |
| `dispatchmng/_backup_dispatch_ss_20260731_2101.sql` | 07-31（分納対応の前） |
