# 画面設計書 102-商品カテゴリ

## 概要

本ドキュメントは、QuickerSiteのECサイト機能における商品カテゴリ割当画面（bs_shopProductCat.asp）の設計書です。商品に対して所属するカテゴリを設定する管理画面について記載しています。

### 本画面の処理概要

商品カテゴリ画面は、登録済みの商品に対して、所属するカテゴリを選択・設定するための画面です。

**業務上の目的・背景**：ECサイトでは、商品を複数のカテゴリに分類することで、ユーザーが目的の商品を見つけやすくなります。本画面では、1つの商品を複数のカテゴリに紐付けることができ、階層化されたカテゴリ（親カテゴリ・サブカテゴリ）構造にも対応しています。これにより、柔軟な商品分類と検索性の向上を実現します。

**画面へのアクセス方法**：バックサイトにログイン後、ショッピングカート管理画面（bs_shoppingcart.asp）の商品一覧から「Categories」ボタンをクリックしてアクセスします。商品管理画面（bs_shopProduct.asp）からは直接遷移できず、必ずショッピングカート管理画面を経由します。

**主要な操作・処理内容**：
1. 対象商品の現在のカテゴリ割当状態を確認（チェック済みカテゴリの表示）
2. カテゴリのチェックボックスをON/OFFで割当の追加・削除を設定
3. 保存ボタンで一括保存（既存の割当をすべて削除後、選択されたカテゴリを新規登録）

**画面遷移**：ショッピングカート管理画面（bs_shoppingcart.asp）から商品IDをパラメータとして遷移してきます。保存後は同画面にとどまり、成功メッセージを表示します。

**権限による表示制御**：セカンドアドミンのbShoppingCart権限を持つユーザーのみがアクセス可能です。権限がない場合はアクセス拒否されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 79 | 商品カテゴリ管理 | 主機能 | 商品のカテゴリ割り当て |

## 画面種別

編集

## URL/ルーティング

`asp/bs_shopProductCat.asp`

パラメータ：
- `iShopProductID`：商品ID（暗号化済み）。必須。

## 入出力項目

| 項目名 | 項目ID | 型 | 必須 | 最大長 | 説明 |
|--------|--------|-----|------|--------|------|
| カテゴリ選択 | cat | checkbox(複数) | - | - | カテゴリ選択チェックボックス（暗号化されたカテゴリID） |
| postback | postback | hidden | - | - | POSTバック判定フラグ |
| iShopProductID | iShopProductID | hidden | - | - | 商品ID（暗号化） |
| QSSEC | QSSEC | hidden | - | - | CSRFトークン |

## 表示項目

| 項目名 | 説明 |
|--------|------|
| 商品名 | 対象商品の名称（読取専用表示） |
| カテゴリ一覧 | 階層構造でチェックボックス付きカテゴリ一覧を表示 |
| 親カテゴリ | 第1階層のカテゴリ（太字表示なし） |
| サブカテゴリ | 第2階層のカテゴリ（親カテゴリ配下にインデント表示） |
| 保存ボタン | カテゴリ割当を保存 |

## イベント仕様

### 1-保存ボタン押下

1. フォームデータをPOSTでbs_shopProductCat.aspに送信
2. btnactionの値が「save」の場合：
   - shopProduct.saveCats(request.form("cat"))を呼び出し
   - 既存のtblQShopProdCatレコードをすべて削除
   - 選択されたカテゴリIDをカンマ区切りで分割
   - 各カテゴリIDを復号化し、tblQShopProdCatに新規登録
3. message.Add("fb_saveOK")で成功メッセージを設定
4. 同画面を再表示

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存ボタン押下 | tblQShopProdCat | DELETE | 対象商品の既存カテゴリ割当をすべて削除 |
| 保存ボタン押下 | tblQShopProdCat | INSERT | 選択されたカテゴリごとにレコードを追加 |

### テーブル別更新項目詳細

#### tblQShopProdCat

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | WHERE iProductID={商品ID} | 既存割当を全削除 |
| INSERT | iProductID | 商品ID | 商品の主キー |
| INSERT | iCategoryID | 選択されたカテゴリID（復号化後） | カテゴリの主キー |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| fb_saveOK | 成功 | 保存が完了しました | 保存処理成功時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 権限なし | セカンドアドミンのbShoppingCart権限がない場合、アクセス拒否 |
| 不正な商品ID | 存在しない商品IDを指定した場合、空のフォームを表示 |
| カテゴリ未選択 | エラーなし（すべてのカテゴリ割当が解除される） |

## 備考

- 商品は複数のカテゴリに所属可能（多対多リレーション）
- カテゴリIDは暗号化されてフォームに埋め込まれる（encrypt関数）
- 保存時に復号化して数値に変換（decrypt関数、convertGetal関数）
- 階層は最大2階層（親カテゴリとサブカテゴリ）
- サブカテゴリの表示は親カテゴリごとにグループ化される
- CSRFトークン（QS_secCodeHidden）による保護が実装されている

---

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

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

### 推奨読解順序

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

商品とカテゴリの関連を理解することが画面の動作把握の第一歩です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | shopProduct.asp | `asp/includes/shopProduct.asp` | categories関数（117-127行目）で現在の割当を取得、saveCats関数（134-143行目）で割当を保存 |
| 1-2 | shopCategory.asp | `asp/includes/shopCategory.asp` | list関数（24-36行目）で親カテゴリ一覧取得、subcategories関数（11-23行目）でサブカテゴリ取得 |

**読解のコツ**: tblQShopProdCatは中間テーブルで、iProductIDとiCategoryIDの組み合わせで商品とカテゴリを紐付けています。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bs_shopProductCat.asp | `asp/bs_shopProductCat.asp` | 画面のメイン処理、カテゴリ一覧の動的生成ロジックを理解 |

**主要処理フロー**:
1. **4行目**: セキュリティチェック
2. **5-6行目**: shopProductオブジェクト生成、商品データ取得
3. **7-9行目**: カテゴリ一覧（catList）取得
4. **10-12行目**: POSTバック処理（saveCats呼び出し）
5. **14行目**: 現在の割当済みカテゴリ取得（categories）
6. **15-32行目**: ネストしたループでカテゴリ一覧HTML生成

#### Step 3: カテゴリ表示ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | bs_shopProductCat.asp | `asp/bs_shopProductCat.asp` | 15-32行目のネストループで階層構造を表示 |

**主要処理フロー**:
- **15行目**: 親カテゴリのループ開始（for each cat in catList）
- **17-18行目**: 現在の割当状態をチェック（categories.exists）
- **21-29行目**: サブカテゴリのループ（for each subcat in subcats）
- **25行目**: サブカテゴリの割当状態もチェック

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

```
bs_shopProductCat.asp
    │
    ├─ begin.asp（初期化処理）
    │      └─ includes/shopProduct.asp（cls_shopProductクラス読込）
    │      └─ includes/shopCategory.asp（cls_shopCategoryクラス読込）
    │
    ├─ bs_security.asp（認証チェック）
    │
    ├─ cls_shopProduct
    │      ├─ pick()（商品データ取得）
    │      ├─ categories()（現在のカテゴリ割当取得）
    │      │      └─ SELECT from tblQShopProdCat
    │      └─ saveCats()（カテゴリ割当保存）
    │             ├─ DELETE from tblQShopProdCat
    │             └─ INSERT into tblQShopProdCat
    │
    └─ cls_shopCategory
           ├─ list()（親カテゴリ一覧）
           └─ subcategories()（サブカテゴリ一覧）
```

### データフロー図

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

ブラウザ（GET）     ───▶ bs_shopProductCat.asp       ───▶ フォームHTML表示
iShopProductID            ├─ shopProduct.pick()              （チェック済み
                          ├─ catList.list()                    カテゴリ表示）
                          ├─ shopProduct.categories()
                          └─ 階層カテゴリHTML生成

ブラウザ（POST）    ───▶ bs_shopProductCat.asp       ───▶ 同画面再表示
cat[]（複数）             ├─ shopProduct.saveCats()          （成功メッセージ）
                          │      ├─ DELETE既存
                          │      └─ INSERT新規
                          └─ message.Add("fb_saveOK")
                                  │
                                  ▼
                          tblQShopProdCat（DB）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bs_shopProductCat.asp | `asp/bs_shopProductCat.asp` | ソース | 商品カテゴリ割当画面本体 |
| shopProduct.asp | `asp/includes/shopProduct.asp` | ソース | 商品データクラス（categories、saveCatsメソッド） |
| shopCategory.asp | `asp/includes/shopCategory.asp` | ソース | カテゴリデータクラス（list、subcategoriesメソッド） |
| bs_shoppingcartmenu.asp | `asp/bs_shoppingcartmenu.asp` | ソース | ナビゲーションメニュー |
| bs_security.asp | `asp/bs_security.asp` | ソース | 認証・権限チェック |
| begin.asp | `asp/begin.asp` | ソース | 共通初期化処理 |
| header.asp | `asp/includes/header.asp` | テンプレート | HTMLヘッダー |
| footer.asp | `asp/includes/footer.asp` | テンプレート | HTMLフッター |
