# 航路変更（前・後）テスト結果と修正記録

**実施日**: 2026-04-8
**対象**: 前航路変更／後航路変更
**テスト方法**: 自動テスト（カシュニの滝 4/11 21時の便にテスト予約を投入して検証）

---

## このドキュメントについて

このドキュメントは、航路変更の機能（前航路変更と後航路変更）について行ったテストの結果と、そこで見つかった問題、そしてその修正内容をまとめたものです。専門用語を避けて書いています。

---

## 「前航路変更」と「後航路変更」って何が違うの？

両方とも「予約を別の船・別の航路に振り替える」機能ですが、**いつ使うか**が違います。

| | 前航路変更 | 後航路変更 |
|---|---|---|
| **画面** | スケジュール編集 | 決済管理 → 条件付き運航 |
| **使うタイミング** | お客さんからまだお金を受け取っていない段階 | お客さんから既にお金を受け取った後 |
| **想定シーン** | 出航のずっと前、計画段階での船の入替え | 出航直前のトラブル対応、当日変更 |
| **お金の動き** | 不要（まだ請求してないので新料金で請求するだけ） | 必要（返金または追加で受け取る） |

**ざっくり言うと**：
- 前 = まだお金もらってない予約 → 値段が変わってもサクッと変更できる
- 後 = もうお金もらった予約 → 返金や追加徴収が発生するので慎重に処理する

---

## 1. 前航路変更のテスト

### テストの目的

「お金を受け取った予約があるのに前航路変更しちゃう」というミスを防ぐ仕組みが正しく動くか確認する。

### テストで確認したこと

| シーン | 期待動作 | 結果 |
|---|---|---|
| 全予約がまだ未入金（仮決済のみ）の状態で前航路変更 | 普通に成功する | ✅ |
| 入金済みの予約が1件でもある状態で前航路変更しようとする | 「できません」と画面でブロックする | ✅ |
| ブロックされた時の警告メッセージ | 「確定済予約が○件あるため前航路変更はできません。後航路変更を使ってください」と表示 | ✅ |

### 安全装置（3段構え）

ミスを防ぐため、3つの場所でチェックしています：

1. **画面の上部に黄色い警告**: 確定済予約がある時は「⚠ 確定済予約があります（○件）」と表示
2. **運航便を変更しようとした瞬間にダイアログでブロック**: 「前航路変更ができません」と表示してOKを押すと元に戻る
3. **万が一を考えてサーバー側でも防御**: 画面でなんとか突破しても、保存時にサーバー側で再度チェックして拒否

### 関連ファイル

- 画面: [admins/schedule_edit.php](admins/schedule_edit.php)

---

## 2. 後航路変更のテスト

### テストの目的

色々なお客さんの状況（現金払い済み、クレジット決済済み、団体予約、まだ未払いなど）で後航路変更を使った時に、お金の精算が正しく記録されるか確認する。

### テストで確認したこと（10シーン）

| # | お客さんの状況 | やったこと | 期待動作 | 結果 |
|---|---|---|---|---|
| 1 | 当日窓口で現金払い済み | 安い航路に振替 | 「窓口で○円返金してね」と表示 | ✅ |
| 2 | 当日窓口で現金払い済み | 高い航路に振替 | 「窓口で○円追加でもらってね」と表示 | ✅ |
| 3 | まだお金を払ってない | 安い航路に振替 | 新しい安い金額で請求するだけ（返金不要） | ✅ |
| 4 | まだお金を払ってない | 高い航路に振替 | 新しい高い金額で請求するだけ | ✅ |
| 5 | 現金払い済み | 「10%割引」だけ適用 | 「○円返金してね」と表示 | ✅ |
| 6 | 団体予約 | 安い航路に振替 | 5枚のチケット全部、新しい料金に書き換わる | ✅ |
| 7 | クレジットカード決済済み | 安い航路に振替 | クレジット会社に自動で返金リクエストを送る | ✅ |
| 8 | 「航路振替」と「割引」を同時 | 両方適用 | 振替後の料金からさらに値引きされる | ✅ |
| 9 | 同じ航路・同じ料金 | 念のため振替 | お金の動きゼロで完了 | ✅ |
| 10 | 2件まとめて処理 | 同じ航路に2件振替 | 2件とも一発で処理される | ✅ |

### 関連ファイル

- 画面: [admins/schedule_payment.php](admins/schedule_payment.php)
- 処理: [admins/api/apply_conditional_changes.php](admins/api/apply_conditional_changes.php)
- プレビュー: [admins/api/preview_conditional_changes.php](admins/api/preview_conditional_changes.php)

---

## 3. 見つかった問題と修正

テストの過程で3つの問題が見つかったので、すべて修正しました。

### 問題1: 請求書の表示が誤解を招く

**症状**:
お客さんが「カシュニの滝 ¥8,000」を予約 → 船トラブルで別航路「¥5,000」に振替した時、請求書を印刷すると「**値引き（38%）−¥3,000**」と表示されてしまっていました。

実際は「値引き」ではなく「**航路が変わって料金が安くなった**」だけなのに、請求書を見たお客さんから「何の38%引きですか？」と聞かれかねない状態でした。

**原因**:
プログラムが、料金が下がった理由を区別せずに「値引き欄」に書き込んでいました。

**修正後**:
- 航路振替だけの場合: 「値引き欄」には触らない（既存の値引き値を保持）
- 値引きだけの場合: そのまま「値引き欄」に記録（従来通り）
- 振替＋値引きの両方: 実際に値引きした分だけ「値引き欄」に記録

**お客さんへの影響**: 請求書の表示が正しくなり、誤解を招かなくなった。

---

### 問題2: 返金額の集計が混ざる

**症状**:
データベースに「返金額 ¥6,000」と記録されていても、実は2つの意味が混在していました：
- 「これから¥6,000を返金しなきゃいけない」（実際に窓口に来てもらう）
- 「料金が¥6,000下がった、でも元々お金もらってないから返金作業は不要」

両方とも「返金額: ¥6,000」と書かれていたため、月末の返金集計で「実際に返金が必要な分」と「返金不要だけど料金が下がった分」が混ざってしまう可能性がありました。

**修正後**:
- お金をもらってない予約の場合: 「返金額」は0として記録（料金変更は新しい合計金額に反映されるだけ）
- お金をもらった予約の場合: 実際に必要な返金額をそのまま記録（変更なし）

**お客さんへの影響**: 月末集計などで「実際に返金が必要な金額」が正しくカウントされるようになる。

---

### 問題3: タブと処理の不一致（潜在的な問題）

**症状**:
管理画面の決済管理ページには「個人枠（管理者予約）」「個人枠（WEB予約）」「団体枠」「当日枠」の4つのタブがあります。

調査の結果、内部的なプログラムの仕組みで、もし将来「このタブだけ後航路変更したい」というボタンを追加した場合、現金払い済みの個人予約だけ処理されない不具合が起きる可能性があることがわかりました。

**現状の運用では問題は起きていません**（後航路変更ボタンは「全タブ一括」で動くため）。ただし、将来のリスクを未然に防ぐため、修正しました。

**修正後**:
タブ別に処理する場合でも、現金払い済みの予約が正しく処理対象になる。

---

### 問題4: 後航路変更が「チケット振替」だけで「航路自体」を変えていなかった（重大）

**症状**:
「後航路変更」という名前の機能なのに、実は**スケジュール本体の航路を変えていなかった**ことが判明しました。

例: お客さんが「カシュニの滝便」を予約 → 船トラブルで「カムイワッカの滝便」に振り替え

**修正前の動作**:

| 項目 | 動作 |
|---|---|
| 予約のチケット種類 | カシュニ → カムイワッカ に書き換え ✅ |
| 予約の料金 | カシュニ料金 → カムイワッカ料金 に書き換え ✅ |
| 返金/追加課金 | 正しく記録 ✅ |
| **スケジュール本体の航路** | **カシュニのまま、変わらない ❌** |
| **スケジュールのステータス** | **「予定通り運航」のまま ❌** |

つまり「**カシュニの滝便のスケジュールに、カムイワッカの滝のチケットを持った乗客が乗る**」という不整合が発生していました。

**何が問題か**:
- QRチェックインの画面では「カシュニの滝便」と表示される
- 搭乗管理表でも「カシュニの滝便」と表示される
- でも乗客のチケットは「カムイワッカの滝」用
- スタッフが画面を見ても「これは何の便なんだ？」と混乱する状態

**原因**:
プログラムの中で「新しい航路の料金を取りに行くため」だけに新運航IDが使われており、**スケジュール本体の航路を切り替えるコードが書かれていなかった**。長年この不整合に気づかれずに残っていた重大なバグです。

**修正内容**:

1. **データベースに2列追加** — 「元の航路を覚えておく」欄を作成
   - `original_operation_id`: 後航路変更前の元の運航ID
   - `original_operation_status`: 後航路変更前の元のステータス

2. **後航路変更時にスケジュール本体も更新**
   - 元の航路ID/ステータスを「元の航路」欄に保存
   - スケジュールの航路を新航路に切り替え
   - スケジュールのステータスを「条件付き運航」に変更

3. **「元に戻す」機能でもスケジュールを復元**
   - 「条件付き運航の設定を元に戻す」ボタンを押した時、チケットだけでなく**スケジュール本体の航路も元に戻る**

4. **多重実行への対応**
   - 後航路変更を2回続けて実施した場合（例: カシュニ→カムイワッカ→秘境知床）でも、「元の航路」は**最初のカシュニ**を保持
   - これにより、「元に戻す」を押すといつでも**最初の状態（カシュニ）**に戻れる

**お客さんへの影響**:
- 後航路変更後、QRチェックインや搭乗管理画面で**正しい航路名**が表示されるようになる
- スタッフが「この便は何だ？」と混乱することがなくなる
- スケジュールに「条件付き運航」のマークが付き、「特別対応中」だと一目でわかる

**検証結果**: 16/16 PASS
- 後航路変更でスケジュールの航路が更新される ✅
- 元の航路情報が保存される ✅
- ステータスが「条件付き運航」になる ✅
- 「元に戻す」で元の航路に戻る ✅
- 「元に戻す」で元の航路情報がクリアされる ✅
- 多重実行で「元の航路」が保護される（上書きされない）✅
- 値引きだけの操作ではスケジュールは変更されない ✅

---

## 4. テストの結果まとめ

### 動作確認

| 項目 | 結果 |
|---|---|
| 前航路変更の安全装置 | ✅ 正しく動作 |
| 後航路変更の10シーン | ✅ 全パス |
| 問題1（請求書表示）の修正後検証 | ✅ 全パス |
| 問題2（返金額集計）の修正後検証 | ✅ 全パス |
| 問題3（タブ別処理）の修正後検証 | ✅ 全パス |
| 問題4（スケジュール本体の航路更新）の修正後検証 | ✅ 全パス（16/16）|

### 修正したファイル

| ファイル | 修正内容 |
|---|---|
| [admins/api/apply_conditional_changes.php](admins/api/apply_conditional_changes.php) | 問題1・2・3・4 すべての修正 |
| [admins/api/preview_conditional_changes.php](admins/api/preview_conditional_changes.php) | 問題3 の修正 |
| [admins/api/revert_conditional_changes.php](admins/api/revert_conditional_changes.php) | 問題4 対応（元に戻す機能でスケジュールも復元） |
| [admins/sql/add_schedules_original_operation.sql](admins/sql/add_schedules_original_operation.sql) | 問題4 対応（スキーマ変更SQL: 元の航路情報を保存する列を追加） |

### 修正後の運用上のメリット

1. **請求書の表示が正しくなった** — お客さんに渡す書類で「何の値引き？」と聞かれることがなくなる
2. **返金集計が正確になった** — 月末の返金合計に余計な金額が混ざらなくなる
3. **将来の不具合を未然に防げた** — タブ別の処理ボタンを追加しても問題が起きない
4. **後航路変更が名前通りに動くようになった** — 予約だけでなく、スケジュール本体の航路も切り替わる。スタッフが画面を見て混乱しなくなる

---

## 5. 残っている検討事項

### 当日枠の前航路変更について

当日枠（窓口で売った予約）は販売と同時に「販売済」状態になります。現状の前航路変更は「販売済の予約があるとブロックされる」設計です。

**保留中の議論**:
「船トラブルで急遽船を入れ替えたい時、当日枠の販売済予約があっても前航路変更を使えるようにすべきか？」

→ 実運用してみないとわからない部分があるため、**現状維持**としています。実運用で不便さや要望が出てきた時点で再検討します。

---

## 補足: テストで使ったテスト予約について

テストはカシュニの滝 4/11 21時の便（スケジュール1876）に予約を投入して実施しました。検証完了後はすべて削除済みで、本番データには影響ありません。
