カスタムメニューページ add_submenu_page('lms-training-plans', ...) として登録。一覧画面(B-PLN-002一覧)の行アクション「詳細」から ?page=lms-member-plan-detail&plan_id={id} でアクセス。閲覧専用のため <form> タグ・保存処理は一切不要。各フィールドは カスタムDBテーブル lms_training_plans および関連テーブルから読み込み、静的HTMLとして出力。講座一覧はカスタムテーブル lms_plan_lectures(計画-講座の中間テーブル)とJOINして取得。メタボックスの折りたたみはWPのpostbox.jsを利用せず、本ワイヤー用の toggleMetabox() で代替。
閲覧権限: manage_lms(事務局担当者)のみアクセス可。法人管理者・事業所管理者はWP管理画面にアクセスできないため、会員サイト側(F-CORP / F-SITE)で研修計画を閲覧・編集する。current_user_can('manage_lms') が false の場合は wp_die() でアクセスを遮断。編集ボタン・削除ボタンは一切表示しない。進捗サマリ・割当先情報は全て読み取り専用。
研修計画: カスタムテーブル lms_training_plans(plan_id, title, description, corp_id, created_by, status, start_date, end_date, created_at, updated_at)。講座割当: lms_plan_lectures(plan_id, lecture_id, lecture_type(web/live), sort_order)。割当先: lms_plan_assignments(plan_id, target_type(site/user), target_id)。進捗: lms_lecture_progress を集計クエリで算出(完了ユーザー数 / 割当ユーザー数)。統計値はトランジェントAPI(TTL: 30分)でキャッシュ。
詳細画面のため一括操作・行アクションは定義しない。画面上部「← 一覧に戻る」リンクで admin.php?page=lms-member-training-plans へ遷移。「📊 受講履歴」ボタンは admin.php?page=lms-history&plan_id={id} へのリンク(B-HST-001)。講座一覧の講座名リンクは admin.php?page=lms-web-lectures&action=view&id={lecture_id}(B-CNT-001 詳細)へ遷移。閲覧専用画面のため nonce の付与は不要(GETリクエストのみ)。
カスタムメニューページのため、WP標準の Screen Options パネルは適用されない。メタボックスの表示/非表示はWPのpostbox.jsを使わず独自の折りたたみ(toggleMetabox())で提供。折りたたみ状態は永続化せず、初期表示をすべて「開く」状態とする。ページ内のテーブル行数はすべて固定表示(ページネーションなし)。
閲覧専用ページのため書き込み系の攻撃(CSRF等)リスクは低いが、URLパラメータ plan_id は必ず absint() で整数化し、存在確認クエリで有効なIDか検証する(不正IDの場合 wp_die())。進捗集計クエリは lms_plan_lectures × lms_lecture_progress の複数JOINになるため負荷が高く、set_transient('lms_plan_progress_' . $plan_id, $data, 1800) で30分キャッシュする。割当先スタッフ数が多い法人(100名超)では集計に数百msかかる可能性があるため、非同期API(REST: /wp-json/lms/v1/plans/{id}/progress)でのLazy Load化を実装時に検討する。SQLは $wpdb->prepare() を必ず使用し、SQLインジェクションを防止する。出力値は esc_html() / esc_url() でエスケープする。