# 機能設計書 63-ゲストブック投稿管理

## 概要

本ドキュメントは、QuickerSite CMSの管理画面におけるゲストブック投稿管理機能の設計を定義する。

### 本機能の処理概要

ゲストブック投稿管理機能は、特定のゲストブックに投稿されたエントリ（コメント）の一覧表示、承認・編集・削除・返信を行う機能である。

**業務上の目的・背景**：ゲストブックへの投稿は、スパムや不適切な内容を含む可能性があるため、管理者による確認と管理が必要である。特に「承認制」に設定されているゲストブックでは、投稿を公開する前に管理者が内容を確認して承認する必要がある。本機能は、これらの投稿管理作業を効率的に行うためのインターフェースを提供する。

**機能の利用シーン**：
- 新規投稿の確認と承認作業
- 不適切な投稿の編集または削除
- ユーザーからの質問への返信入力
- 投稿者情報（名前、メール、IP）の確認
- スパム投稿の一括削除

**主要な処理内容**：
1. 指定ゲストブックの全投稿一覧取得・表示
2. 各投稿の承認状態の変更
3. 投稿内容（メッセージ、投稿者名）の編集
4. 管理者返信の入力・更新
5. 投稿の削除処理
6. 一括保存処理

**関連システム・外部連携**：特になし（CMS内部機能）

**権限による制御**：セカンドアドミン権限のbGuestbookフラグによりアクセス制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 61 | エントリー管理 | 主画面 | ゲストブック投稿の承認・編集・削除 |
| 59 | ゲストブック一覧 | 参照画面 | 戻り先画面 |

## 機能種別

CRUD操作（Read/Update/Delete）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| iGBID | String (暗号化) | Yes | ゲストブックID（クエリストリング） | decrypt後にisNumeriek |
| postBack | Boolean | No | ポストバックフラグ | true/false |
| iGBItemID | Array | No | 投稿ID配列（複数） | 数値 |
| sValue{ID} | Text | No | 投稿メッセージ（IDごと） | - |
| sReply{ID} | Text | No | 管理者返信（IDごと） | - |
| sAuthor{ID} | String | No | 投稿者名（IDごと） | 最大50文字 |
| approve{ID} | Boolean | No | 承認フラグ（IDごと） | true/false |
| remove{ID} | Boolean | No | 削除フラグ（IDごと） | true/false |

### 入力データソース

- 画面入力フォーム
- データベーステーブル: tblGuestbookItem（一覧取得）
- データベーステーブル: tblGuestbook（ゲストブック情報）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| iId | Integer | 投稿ID |
| ip | String | 投稿者IPアドレス |
| sMessageBy | String | 投稿者名 |
| sMessageByEmail | String | 投稿者メールアドレス |
| sValue | Text | 投稿メッセージ |
| sReply | Text | 管理者返信 |
| bApproved | Boolean | 承認状態 |

### 出力先

HTML画面（管理画面内）、データベース

## 処理フロー

### 処理シーケンス

```
1. アクセス権限チェック
   └─ secondAdmin.bGuestbook権限の確認
2. ゲストブック読み込み
   └─ iGBIDパラメータからゲストブック取得
3. ポストバック処理
   └─ postBack=trueの場合
   └─ CSRFチェック
   └─ 各投稿IDでループ処理
       ├─ 投稿データ読み込み（pick）
       ├─ フォーム値をセット
       ├─ 削除フラグ確認
       │   ├─ 削除フラグON: remove()実行
       │   └─ 削除フラグOFF: save()実行
       └─ 次の投稿へ
   └─ 保存完了メッセージ表示
4. 投稿一覧取得
   └─ guestbook.entries()でDictionary取得
5. 画面表示
   └─ テーブル形式で一覧表示
   └─ 各投稿の編集フォーム生成
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{bGuestbook権限あり?}
    B -->|No| C[アクセス拒否]
    B -->|Yes| D[ゲストブック読込]
    D --> E{postBack?}
    E -->|Yes| F[CSRFチェック]
    F --> G[投稿IDループ開始]
    G --> H[投稿データ読込]
    H --> I[フォーム値セット]
    I --> J{削除フラグON?}
    J -->|Yes| K[remove実行]
    J -->|No| L[save実行]
    K --> M{次の投稿あり?}
    L --> M
    M -->|Yes| G
    M -->|No| N[保存完了メッセージ]
    N --> O[投稿一覧取得]
    E -->|No| O
    O --> P[一覧表示]
    P --> Q[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 一括処理 | 複数投稿の変更を一括で保存 | 保存ボタン押下時 |
| BR-002 | 削除優先 | 削除フラグON時は更新せず削除 | 各投稿処理時 |
| BR-003 | 降順表示 | 投稿は新しい順（dCreatedTS desc）で表示 | 一覧表示時 |
| BR-004 | ページキャッシュクリア | 投稿保存時にページキャッシュをクリア | save実行時 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧取得 | tblGuestbookItem | SELECT | ゲストブックIDで絞り込み、作成日時降順 |
| 更新 | tblGuestbookItem | UPDATE | 投稿内容、返信、承認状態の更新 |
| 削除 | tblGuestbookItem | DELETE | 指定投稿の削除 |

### テーブル別操作詳細

#### tblGuestbookItem

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | iGuestBookID = 対象ID、ORDER BY dCreatedTS DESC | entries()メソッド |
| UPDATE | sValue | 入力メッセージ | 最大5000文字 |
| UPDATE | sMessageBy | 入力投稿者名 | 最大50文字 |
| UPDATE | bApproved | 入力承認フラグ | - |
| UPDATE | sReply | 入力管理者返信 | - |
| DELETE | - | iId条件 | remove()メソッド |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 権限エラー | bGuestbook権限なし | アクセス拒否 |
| - | データなし | 指定投稿IDが存在しない | スキップして次へ |

### リトライ仕様

エラー時は処理をスキップし、次の投稿処理を継続

## トランザクション仕様

各投稿の保存/削除は個別のトランザクション（ADO自動コミット）。一括処理でも投稿ごとに独立。

## パフォーマンス要件

- 一覧表示: 2秒以内
- 一括保存: 5秒以内（投稿数に依存）

## セキュリティ考慮事項

- セカンドアドミン権限によるアクセス制御
- CSRFトークン（checkCSRF()）による保存操作の保護
- IDパラメータの暗号化（encrypt/decrypt関数）
- 出力値のサニタイズ（sanitize関数）
- 投稿者メールアドレスのmailtoリンク表示

## 備考

- 投稿一覧はguestbook.entries()メソッドでDictionary形式で取得
- 各投稿データはQS_VBScriptIdentifier区切りの文字列で格納
- フォームには投稿IDごとの名前属性（sValue{ID}など）を使用

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

投稿（エントリ）のデータモデルを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | guestbookitem.asp | `asp/includes/guestbookitem.asp` | cls_guestbookitemクラスのプロパティ定義（2-13行目） |
| 1-2 | guestbook.asp | `asp/includes/guestbook.asp` | entries()メソッドの実装（285-302行目） |

**読解のコツ**: entries()メソッドはDictionaryを返し、各値はQS_VBScriptIdentifier区切りの文字列。split関数で分解して使用する。

#### Step 2: エントリーポイントを理解する

処理の起点となるASPファイルを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bs_gbEditItems.asp | `asp/bs_gbEditItems.asp` | メイン処理フロー（1-32行目） |

**主要処理フロー**:
1. **4行目**: セキュリティチェック（logon.hasaccess secondAdmin.bGuestbook）
2. **5-6行目**: cls_guestbookインスタンス生成
3. **7-8行目**: postBackフラグ確認
4. **9行目**: checkCSRF()によるCSRFチェック
5. **10-25行目**: Request.Form("iGBItemID")でループ、各投稿を処理
6. **11-12行目**: cls_guestbookitem生成、pick()でデータ読込
7. **14-17行目**: フォーム値をプロパティにセット
8. **18-22行目**: 削除/保存の分岐処理
9. **26行目**: 保存完了メッセージ追加
10. **28-29行目**: guestbook.entriesで一覧取得
11. **29-31行目**: 一覧テーブル生成

#### Step 3: 投稿データ操作を理解する

保存・削除処理の詳細を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | guestbookitem.asp | `asp/includes/guestbookitem.asp` | pick()メソッド（45-64行目） |
| 3-2 | guestbookitem.asp | `asp/includes/guestbookitem.asp` | save()メソッド（83-138行目）、特に更新時の処理（124-137行目） |
| 3-3 | guestbookitem.asp | `asp/includes/guestbookitem.asp` | remove()メソッド（139-145行目） |

**主要処理フロー**:
- **45-64行目**: pick()でiIdからレコード取得
- **83-138行目**: save()で新規/更新判定、ADO Recordsetで保存
- **137行目**: selectedPage.clearPageCache()でキャッシュクリア
- **139-145行目**: remove()でDELETE実行

### プログラム呼び出し階層図

```
bs_gbEditItems.asp
    │
    ├─ bs_security.asp
    │      └─ logon.hasaccess (権限チェック)
    │
    ├─ cls_guestbook (インスタンス生成)
    │      └─ pick() (ゲストブック情報読込)
    │      └─ entries() (投稿一覧取得)
    │             └─ SELECT tblGuestbookItem
    │
    └─ cls_guestbookitem (各投稿処理)
           ├─ pick() (投稿読込)
           ├─ save() (投稿保存)
           │      └─ UPDATE tblGuestbookItem
           │      └─ clearPageCache()
           └─ remove() (投稿削除)
                  └─ DELETE tblGuestbookItem
```

### データフロー図

```
[入力]               [処理]                    [出力]

フォームPOST ───▶ bs_gbEditItems.asp ───▶ 画面再表示
(複数投稿)              │
                       ▼
               ループ処理 ───▶ cls_guestbookitem
                       │
                       ▼
               save()/remove() ───▶ tblGuestbookItem（UPDATE/DELETE）
                       │
                       ▼
               entries() ───▶ Dictionary（一覧表示用）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bs_gbEditItems.asp | `asp/bs_gbEditItems.asp` | ソース | 投稿管理画面のメイン処理 |
| guestbook.asp | `asp/includes/guestbook.asp` | ソース | cls_guestbookクラス（entries()メソッド含む） |
| guestbookitem.asp | `asp/includes/guestbookitem.asp` | ソース | cls_guestbookitemクラス定義 |
| bs_security.asp | `asp/bs_security.asp` | ソース | 権限チェック処理 |
| urlenCodeJS.asp | `asp/includes/urlenCodeJS.asp` | ソース | URL/JavaScript文字列エンコード |
| header.asp | `asp/includes/header.asp` | テンプレート | HTMLヘッダー |
| footer.asp | `asp/includes/footer.asp` | テンプレート | HTMLフッター |
