九州の友人から贈り物 施工計画書見直し

天気が良い、元宇品の海岸を散歩
ニンニクとジャガイモを送っていただいた

建設アシストの中で、最も難しいと言える【施工計画書】の作成について、大幅に見直しを実施する・・施工計画書のタイプは、官庁系、民間系、建築系、土木系、設備系と種類が多く、様式も組織によって、発注者によっていろいろな種別があり統一性が難しい
今までは、官庁系が主体の土木系に絞って作成をしていたが、色々な様式とタイプに対応するべく、全体の構成をフレキシブルなものに変えて、カスタム性を強くする・・・また、合わせてセキュリティ面、コードの健全性も考慮する

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.phpAI整形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ファイルに集中している。以下に分割を推奨:

分割先対象メソッド
ConstructionPlanItemControllereditItem, updateItem, printItem, uploadItemImage
ConstructionPlanAiControlleraiPrintItem, aiPreviewItem, storeAiFormatPreset, destroyAiFormatPreset
ConstructionPlanTemplateControllerstoreTemplate, updateTemplate, destroyTemplate, importTemplate 系
ConstructionPlanDiagramControllerdiagramEditor, saveDiagram, getDiagramTemplates, storeDiagramTemplate 系
ConstructionPlanExportControllergeneratePdf, 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.jsCSP対応版(@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 を撤廃し、種別ごとの動的なカテゴリを持つ
セクション自由度の拡張:各項目に複数のコンテンツブロック(ページ)を柔軟に追加できる
テンプレートの体系化:計画書種別 × カテゴリ × 発注者でテンプレートを管理

ブックマーク パーマリンク.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

  • 2026年7月
     12345
    6789101112
    13141516171819
    20212223242526
    2728293031