# 画面設計書 50-国設定

## 概要

本ドキュメントは、Shopware 6 Administration（管理画面）における「国設定」画面の設計書です。この画面は配送先国・地域の設定を行うローカライゼーション管理機能を提供します。

### 本画面の処理概要

**業務上の目的・背景**：ECサイト運営において、配送可能な国・地域の管理は物流とコンプライアンスの観点から重要です。各国には異なる税率、配送制限、住所フォーマットが存在するため、国ごとの詳細設定が必要です。本画面は、国・地域の一覧管理、州/県の設定、住所フォーマットのカスタマイズなどを行う機能を提供します。

**画面へのアクセス方法**：管理画面にログイン後、左側メニューの「設定」→「国」をクリックすることでアクセスできます。URLパスは `/admin#/sw/settings/country/index` となります。`country.viewer` 権限を持つユーザーのみがアクセス可能です。

**主要な操作・処理内容**：
1. 国一覧の表示 - 登録済みの国を一覧表示
2. 国の検索 - キーワードによる絞り込み
3. 国の新規作成 - 新しい国を追加
4. 国の編集 - 国の設定を編集（基本情報、州/県、住所フォーマット）
5. 国の削除 - 不要な国を削除
6. インライン編集 - 一覧上での直接編集

**画面遷移**：
- 遷移元: ダッシュボード、設定メニュー
- 遷移先: 国詳細画面（sw.settings.country.detail）、国作成画面（sw.settings.country.create）

**権限による表示制御**：
- `country.viewer`: 閲覧権限 - 国一覧の表示が可能
- `country.creator`: 作成権限 - 新規作成ボタンが表示
- `country.editor`: 編集権限 - 編集が可能
- `country.deleter`: 削除権限 - 削除ボタンが表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 65 | ローカライゼーション | 主機能 | 配送先国・地域の設定 |

## 画面種別

一覧/詳細（タブ切替: 基本設定 / 州/県 / 住所フォーマット）

## URL/ルーティング

- **パス**: `/admin#/sw/settings/country/index`（一覧）、`/admin#/sw/settings/country/detail/:id`（詳細）
- **コンポーネント**: `sw-settings-country-list`（一覧）、`sw-settings-country-detail`（詳細）
- **ルート名**: `sw.settings.country.index`（一覧）、`sw.settings.country.detail`（詳細）
- **必要権限**: `country.viewer`

## 入出力項目

| 項目名 | 種別 | 型 | 必須 | 説明 |
|--------|------|-----|------|------|
| term | 入力 | string | - | 検索キーワード |
| page | 入力 | number | - | ページ番号 |
| limit | 入力 | number | - | 1ページあたりの表示件数 |
| sortBy | 入力 | string | - | ソート対象カラム（デフォルト: country.name） |
| sortDirection | 入力 | string | - | ソート方向（デフォルト: ASC） |

## 表示項目

| 項目名 | カラム名 | 説明 | 編集可否 |
|--------|----------|------|----------|
| 国名 | name | 国の名称（詳細へのリンク） | インライン編集可 |
| 位置 | position | 表示順序 | インライン編集可 |
| ISO | iso | 2文字の国コード | インライン編集可 |
| ISO3 | iso3 | 3文字の国コード | インライン編集可 |
| 有効 | active | 有効/無効の状態 | インライン編集可 |

## イベント仕様

### 1-ページ読み込み（getList）

画面初期表示時に国一覧を取得する。

**処理フロー**:
1. `isLoading` を `true` に設定
2. `Criteria` を構築（ページ、リミット、ソート、検索条件）
3. `countryRepository.search(criteria, Shopware.Context.api)` でデータを取得
4. 取得結果を `country` データに格納
5. `total` を更新
6. `isLoading` を `false` に設定

### 2-検索実行

検索ボックスにキーワードを入力し検索を実行。

**処理フロー**:
1. `term` が設定される
2. `criteria.setTerm(this.term)` で検索条件を設定
3. `getList()` を再実行

### 3-ソート変更

カラムヘッダーをクリックしてソート条件を変更。

**処理フロー**:
1. `sortBy` と `sortDirection` を更新
2. `naturalSorting` を `sortBy === 'name'` で判定
3. `getList()` を再実行

### 4-インライン編集保存（onInlineEditSave）

一覧上で直接編集して保存。

**処理フロー**:
1. 編集した行のデータを取得
2. `promise` で保存結果を待機
3. 成功時、`createNotificationSuccess()` で成功通知を表示
4. 失敗時、`getList()` で再取得し、`createNotificationError()` でエラー通知を表示

### 5-言語変更（onChangeLanguage）

表示言語を切り替え。

**処理フロー**:
1. `Shopware.Store.get('context').api.languageId` を更新
2. `getList()` を再実行

### 6-削除確認（onDelete）

削除ボタンをクリック。

**処理フロー**:
1. `showDeleteModal` に削除対象のIDを設定
2. 削除確認モーダルを表示

### 7-削除実行（onConfirmDelete）

削除確認モーダルで確定。

**処理フロー**:
1. `showDeleteModal` を `false` に設定
2. `countryRepository.delete(id)` を実行
3. 成功時、`getList()` を再実行

### 8-削除キャンセル（onCloseDeleteModal）

削除確認モーダルをキャンセル。

**処理フロー**:
1. `showDeleteModal` を `false` に設定

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 国一覧取得 | country | SELECT | 国データの取得 |
| 国作成 | country | INSERT | 新規国の作成 |
| 国更新 | country | UPDATE | 国情報の更新 |
| 国削除 | country | DELETE | 国の削除 |
| 州/県作成 | country_state | INSERT | 州/県の追加 |
| 州/県更新 | country_state | UPDATE | 州/県の更新 |
| 州/県削除 | country_state | DELETE | 州/県の削除 |

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

#### country

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | ページネーション、ソート、検索条件 | 一覧取得 |
| INSERT | name, iso, iso3, position, active, ... | 入力値 | 新規作成 |
| UPDATE | name, iso, iso3, position, active, ... | 入力値 | 更新時 |
| DELETE | - | id指定 | 削除時 |

#### country_state

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | country_id指定 | 詳細画面で取得 |
| INSERT | name, short_code, position, active, country_id | 入力値 | 州/県追加 |
| UPDATE | name, short_code, position, active | 入力値 | 州/県更新 |
| DELETE | - | id指定 | 州/県削除 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| sw-settings-country.detail.messageSaveSuccess | 成功 | 保存しました | インライン編集成功時 |
| sw-settings-country.detail.messageSaveError | エラー | 保存に失敗しました | インライン編集失敗時 |

## 例外処理

| 例外ケース | 処理内容 |
|-----------|---------|
| 検索結果0件 | 空状態の画面を表示 |
| インライン編集失敗 | エラー通知を表示、一覧を再取得 |
| 削除失敗 | エラー通知を表示 |
| 権限不足 | 該当機能のボタンを非表示/無効化 |

## 備考

- 国データはShopwareのコアデータとして提供され、初期インストール時に主要国が登録される
- 各国には州/県（country_state）を複数登録可能
- 住所フォーマットは国ごとにカスタマイズ可能で、スニペットを使用してテンプレート化
- ISO/ISO3コードは国際標準規格に準拠
- デフォルトソートは名前の自然順（naturalSorting）でASC

---

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

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

### 推奨読解順序

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

国エンティティと関連エンティティの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CountryDefinition | `src/Core/System/Country/CountryDefinition.php` | 国エンティティの定義 |
| 1-2 | CountryStateDefinition | `src/Core/System/Country/Aggregate/CountryState/CountryStateDefinition.php` | 州/県エンティティ |

**読解のコツ**: Countryは州/県（CountryState）をOneToMany関連で持ち、配送方法・支払方法との関連も持つ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/index.js` | モジュール登録、ルート定義 |

**主要処理フロー**:
1. **44-165行**: `Module.register('sw-settings-country', ...)` でモジュールを登録
2. **54-115行**: `routes` でルート定義（index, detail, create）
3. **78-113行**: `detail.children` で詳細画面のタブ定義（general, state, address-handling）
4. **159-164行**: `settingsItem` で設定メニューへの登録

#### Step 3: 一覧画面コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sw-settings-country-list/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/page/sw-settings-country-list/index.js` | Vue.jsコンポーネントの定義 |

**主要処理フロー**:
- **19-21行**: `mixins` - listingミックスインの使用
- **23-32行**: `data()` - コンポーネントの状態定義
- **56-77行**: `getList()` - 国データ取得処理
- **79-91行**: `onInlineEditSave()` - インライン編集保存
- **115-146行**: `getCountryColumns()` - テーブルカラム定義

#### Step 4: ACL定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | acl/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/acl/index.js` | 権限定義 |

**ACLの詳細**:
- **viewer**: country:read, country_state:read, custom_field_set:read等
- **editor**: country:update, country_state:create/update/delete
- **creator**: country:create
- **deleter**: country:delete

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

```
sw-settings-country-list (Vue Component)
    │
    ├─ getList()
    │      └─ countryRepository.search(criteria)
    │             └─ Shopware API (POST /api/search/country)
    │
    ├─ onInlineEditSave(promise, country)
    │      └─ promise (リポジトリのsave結果)
    │             └─ createNotificationSuccess() / createNotificationError()
    │
    └─ onConfirmDelete(id)
           └─ countryRepository.delete(id)
                  └─ Shopware API (DELETE /api/country/{id})
```

### データフロー図

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

検索キーワード ─────────┐
                        │
ソート設定 ─────────────┼──▶ sw-settings-country-list
                        │         │
ページング ─────────────┘         ├──▶ Criteria構築
                                  │         │
                                  │         ▼
                                  │    countryRepository.search()
                                  │         │
                                  │         ▼
                                  │    Shopware API
                                  │         │
                                  │         ▼
                                  └──▶ country データ ──▶ 一覧表示

言語切替 ──────────────▶ onChangeLanguage()
                                  │
                                  ├──▶ context.api.languageId更新
                                  │
                                  └──▶ getList() ──▶ 一覧再取得
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/index.js` | ソース | モジュール定義 |
| sw-settings-country-list/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/page/sw-settings-country-list/index.js` | ソース | 一覧画面コンポーネント |
| sw-settings-country-list.html.twig | `src/Administration/Resources/app/administration/src/module/sw-settings-country/page/sw-settings-country-list/sw-settings-country-list.html.twig` | テンプレート | 一覧テンプレート |
| sw-settings-country-detail/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/page/sw-settings-country-detail/index.js` | ソース | 詳細画面コンポーネント |
| sw-settings-country-general/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/component/sw-settings-country-general/index.js` | ソース | 基本設定タブ |
| sw-settings-country-state/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/component/sw-settings-country-state/index.js` | ソース | 州/県タブ |
| sw-settings-country-address-handling/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/component/sw-settings-country-address-handling/index.js` | ソース | 住所フォーマットタブ |
| acl/index.js | `src/Administration/Resources/app/administration/src/module/sw-settings-country/acl/index.js` | ソース | 権限定義 |
| CountryDefinition.php | `src/Core/System/Country/CountryDefinition.php` | ソース | エンティティ定義 |
