建設アシストの中で、最も難しいと言える【施工計画書】の作成について、大幅に見直しを実施する・・施工計画書のタイプは、官庁系、民間系、建築系、土木系、設備系と種類が多く、様式も組織によって、発注者によっていろいろな種別があり統一性が難しい
今までは、官庁系が主体の土木系に絞って作成をしていたが、色々な様式とタイプに対応するべく、全体の構成をフレキシブルなものに変えて、カスタム性を強くする・・・また、合わせてセキュリティ面、コードの健全性も考慮する
1.現状調査結果
1-1.ファイル構成と役割
| resources/views/construction_plans/index.blade.php | 大項目一覧(1〜24番 + 表紙・目次)のチェック管理画面 |
| resources/views/construction_plans/print_item.blade.php | 個別項目のPDF印刷用ビュー(キャッシュ無効化・A4最適化) |
| resources/views/construction_plans/ai_print_item.blade.php | AI整形HTMLの編集・出力画面(Word/Excel生成機能付き) |
| resources/views/construction_plans/diagram_editor.blade.php | フローチャート・図面エディタ(A4キャンバス・テンプレート機能) |
| app/Http/Controllers/ConstructionPlanController.php | メインコントローラー(1,550行・39メソッド) |
| app/Models/ConstructionPlan.php | 施工計画書モデル(プロジェクトと1:1) |
| app/Models/ConstructionPlanItem.php | 大項目モデル(TipTap JSON対応) |
| app/Models/ConstructionPlanImage.php | 画像管理モデル |
| app/Models/ConstructionPlanTemplate.php | テンプレートモデル(会社別/共通) |
コントローラーに editItem() メソッドと editPlan() メソッドがあり、それぞれ
construction_plans.edit_item と construction_plans.edit_plan を参照しているが、ファイルが存在しない。
これはルーティングエラーの原因となる可能性がある。
調査時点では該当ルートが routes/web.php に登録されているかは要確認。
1.2 データベース構造と関連性

2.2 🟡 バグ・不具合の恐れ
■存在しないビューの参照
editItem() → construction_plans.edit_item
editPlan() → construction_plans.edit_plan
これらのビューファイルが存在しない。 ルートが定義されていれば 500 エラーになる。
削除済みのページか、実装途中かを確認して対処が必要。
■bulkUpdate() のアイテム所有者未検証
php
foreach ($itemsData as $itemId => $data) {
ConstructionPlanItem::where(‘id’, $itemId)->update([…]);
}
$itemId がこのプロジェクトに属するか検証していない。
修正案: ->where(‘construction_plan_id’, $plan->id) を条件に追加する。
■diagram_json のキャスト不整合
ConstructionPlanItem モデルの $casts に diagram_json が含まれていないが、
saveDiagram() では DB::table() の直接アクセスで対処している。
一貫性がなく、将来的なバグの原因になる。
■category_number が 0 の重複問題
表紙と目次の両方が category_number = 0 で、sort_order で区別している。
フィルタ処理や一意性確保の観点から -1(表紙)-2(目次)等に分けることを推奨。
2.3 🟡 無駄・重複コード
■レガシーカラムの放置
content_1〜content_4 はレガシーの text カラムで、実際には content_1_json・content_2_json が使用されている。
マイグレーションで削除する(または nullable のまま保持してデータ移行後に削除)。
■コントローラーが肥大化(1,550行)
39メソッドが1ファイルに集中している。以下に分割を推奨:
| 分割先 | 対象メソッド |
|---|---|
| ConstructionPlanItemController | editItem, updateItem, printItem, uploadItemImage |
| ConstructionPlanAiController | aiPrintItem, aiPreviewItem, storeAiFormatPreset, destroyAiFormatPreset |
| ConstructionPlanTemplateController | storeTemplate, updateTemplate, destroyTemplate, importTemplate 系 |
| ConstructionPlanDiagramController | diagramEditor, saveDiagram, getDiagramTemplates, storeDiagramTemplate 系 |
| ConstructionPlanExportController | generatePdf, downloadDocx, downloadXlsx, generateDocxFromHtml, generateXlsxFromHtml |
■PDF/Word/Excel生成の重複ロジック
generatePdf(), downloadDocx(), downloadXlsx(), generateDocxFromHtml(), generateXlsxFromHtml()` に
共通の前処理(項目取得・HTML変換)が重複している。
ConstructionPlanExportService として共通化を推奨。
2.4 CLAUDE.md との相違点
| 項目 | CLAUDE.md規定 | 現状 | 対応 |
|---|---|---|---|
| session(‘success’) の表示 | errorのみ表示 | index.blade.php でsuccess表示している | 削除する |
| インラインイベントハンドラ | addEventListener使用 | ai_print_item.blade.phpに onclick=”” 多数あり | 外部JSまたはaddEventListenerに変更 |
| Alpine.js | CSP対応版(@alpinejs/csp)使用 | 確認必要 | 要確認 |
| ヘルプモーダル | 全ページに【Help】ボタン必須 | print_item.blade.php・diagram_editor.blade.php はスタンドアロン(ヘッダーなし)のため例外扱い可 | 対応不要 |
| ボタンの実装 | <x-submit-button> を使用 | ai_print_item.blade.php で通常 タグを直接使用している箇所がある | x-submit-button に変更 |
| ファイル先頭のコメント | ファイルの説明文を記載 | コントローラーに記載あり、モデルはまちまち | モデルにも追加する |
2.コードの健全性確認
2.1 🔴 セキュリティ脆弱性(緊急対応が必要)
■認可チェック未実装のエンドポイント
以下のメソッドに authorizeProject() または authorize() が実装されていない。
任意の認証済みユーザーが他社・他プロジェクトのデータを操作できる状態。
| メソッド | エンドポイント | 影響 |
|---|---|---|
| uploadItemImage() | POST /api/construction-plan-items/{item}/upload-image | 他社項目への画像挿入が可能 |
| storeAiFormatPreset() | POST /post/ai-format-presets | プリセットの不正作成 |
| destroyAiFormatPreset() | DELETE /post/ai-format-presets/{preset} | 他社プリセットの削除 |
| storeTemplate() | テンプレート操作系API | テンプレートの不正作成 |
| updateTemplate() | テンプレート操作系API | 他社テンプレートの上書き |
| destroyTemplate() | テンプレート操作系API | テンプレートの不正削除 |
| storeDiagramTemplate() | 図面テンプレートAPI | 不正テンプレート登録 |
| destroyDiagramTemplate() | 図面テンプレートAPI | テンプレート不正削除 |
修正案: 各メソッドに $item->plan->project 経由でのプロジェクト所有者確認を追加する。
■ファイルアップロードのMIMEタイプ検証不足
uploadItemImage() のバリデーションが image ルールのみで、MIMEタイプの明示的検証がない。
悪意あるファイルをアップロードされるリスクがある。
php
// 現状(不十分)
‘image’ => ‘required|image|max:10240’
// 修正案
‘image’ => ‘required|image|mimes:jpeg,png,gif,webp|max:10240’
■セッションベースのHTML受け渡し
aiPreviewItem() でセッションから AI 生成 HTML を取得して表示している。
セッション奪取によって任意の HTML がレンダリングされる可能性がある。
修正案: セッションの代わりに DB への一時保存(TTL付き)方式に変更する。
■AI API エラーの詳細露出
saveDiagram() で $e->getMessage() をそのまま JSON で返却している。
修正案: エラーメッセージをログに記録し、ユーザーには汎用メッセージのみ返す。
3.システム改善案(指示3:DB構造を含む全体設計)
3-1.現状の問題の本質
現在の施工計画書システムは 「国土交通省土木工事向け24カテゴリ固定」 を暗黙の前提として設計されている。
これにより以下の問題が発生している:
- 建築系(建設省・特定行政庁様式)では全く異なる項目体系が必要
- 発注者(国・県・民間・自社)によって提出書類の種類・数・名称が異なる
- 工事の種別(道路・橋梁・河川・建築・設備・電気)によってセクション構成が異なる
- 24カテゴリはハードコードされており、動的な追加・変更・削除ができない
3-2.新DB設計案
■基本方針
計画書種別(PlanType) を導入:工事の種類と発注者を組み合わせたマスターを管理
カテゴリ定義テーブル を分離:固定 1〜24 を撤廃し、種別ごとの動的なカテゴリを持つ
セクション自由度の拡張:各項目に複数のコンテンツブロック(ページ)を柔軟に追加できる
テンプレートの体系化:計画書種別 × カテゴリ × 発注者でテンプレートを管理




