# ロゲイニングシステム 外部API仕様書

## 概要
本仕様書は、スマホアプリなどの外部システムからロゲイニングシステムへアクセスするためのAPI仕様を定義しています。

## 基本情報
- **ベースURL**: `https://yourdomain.com/api/`
- **認証方式**: Knox Token認証
- **データ形式**: JSON
- **文字エンコーディング**: UTF-8

## 認証について
APIへのアクセスには認証トークンが必要です。ログイン後に取得したトークンをHTTPヘッダーに含めてリクエストしてください。

```http
Authorization: Token <your_token>
Content-Type: application/json
```

---

## 1. ユーザー登録関連API

### 1.1 仮ユーザー登録
新規ユーザーの仮登録を行います。

**エンドポイント**: `POST /register/`

**リクエストパラメータ**:
```json
{
  "email": "user@example.com",
  "password": "password123",
  "firstname": "太郎",
  "lastname": "田中",
  "date_of_birth": "1990-01-01",
  "female": false,
  "is_rogaining": true
}
```

**レスポンス（成功時）**:
```json
{
  "message": "Verification email sent"
}
```

**レスポンス（エラー時）**:
```json
{
  "email": ["この email は既に存在します。"],
  "password": ["この項目は必須です。"]
}
```

### 1.2 メール認証
仮登録後のメール認証を行います。

**エンドポイント**: `GET /verify-email/<verification_code>/`

**レスポンス（成功時）**:
```json
{
  "message": "ユーザー登録が完了しました。",
  "user": {
    "id": 1,
    "email": "user@example.com",
    "firstname": "太郎",
    "lastname": "田中"
  },
  "token": "abcd1234efgh5678ijkl9012mnop3456"
}
```

### 1.3 ログイン
ユーザーの認証を行い、アクセストークンを取得します。

**エンドポイント**: `POST /login/`

**リクエストパラメータ**:
```json
{
  "identifier": "user@example.com",
  "password": "password123"
}
```

**レスポンス（成功時）**:
```json
{
  "user": {
    "id": 1,
    "email": "user@example.com",
    "firstname": "太郎",
    "lastname": "田中",
    "female": false,
    "date_of_birth": "1990-01-01"
  },
  "token": "abcd1234efgh5678ijkl9012mnop3456"
}
```

### 1.4 ユーザー情報取得
現在ログイン中のユーザー情報を取得します。

**エンドポイント**: `GET /user/`

**レスポンス（成功時）**:
```json
{
  "id": 1,
  "email": "user@example.com",
  "firstname": "太郎",
  "lastname": "田中",
  "female": false,
  "date_of_birth": "1990-01-01"
}
```

---

## 2. チーム登録とメンバー管理API

### 2.1 チーム作成
新しいチームを作成します。

**エンドポイント**: `POST /teams/`

**リクエストパラメータ**:
```json
{
  "team_name": "チーム名",
  "category": 1
}
```

**レスポンス（成功時）**:
```json
{
  "id": 1,
  "team_name": "チーム名",
  "owner": 1,
  "category": {
    "id": 1,
    "category_name": "一般男子",
    "duration": 180,
    "num_of_member": 4
  }
}
```

### 2.2 チーム一覧取得
ログイン中のユーザーが所有するチームの一覧を取得します。

**エンドポイント**: `GET /teams/`

**レスポンス（成功時）**:
```json
[
  {
    "id": 1,
    "team_name": "チーム名",
    "owner": 1,
    "category": {
      "id": 1,
      "category_name": "一般男子"
    }
  }
]
```

### 2.3 メンバー追加
チームにメンバーを追加します。

**エンドポイント**: `POST /teams/{team_id}/members/`

**リクエストパラメータ**:
```json
{
  "email": "member@example.com",
  "firstname": "花子",
  "lastname": "佐藤",
  "date_of_birth": "1992-03-15",
  "female": true
}
```

**レスポンス（成功時）**:
```json
{
  "message": "Invitation email sent to the user."
}
```

### 2.4 チームメンバー一覧取得
チームのメンバー一覧を取得します。

**エンドポイント**: `GET /teams/{team_id}/members-with-user/`

**レスポンス（成功時）**:
```json
[
  {
    "id": 1,
    "user": {
      "id": 1,
      "email": "user@example.com",
      "firstname": "太郎",
      "lastname": "田中",
      "female": false
    }
  },
  {
    "id": 2,
    "user": {
      "id": 2,
      "email": "member@example.com",
      "firstname": "花子",
      "lastname": "佐藤",
      "female": true
    }
  }
]
```

---

## 3. イベントエントリーAPI

### 3.1 カテゴリ一覧取得
エントリー可能なカテゴリの一覧を取得します。

**エンドポイント**: `GET /categories/`

**レスポンス（成功時）**:
```json
[
  {
    "id": 1,
    "category_name": "一般男子",
    "duration": 180,
    "num_of_member": 4,
    "family": false,
    "female": false
  },
  {
    "id": 2,
    "category_name": "ファミリー",
    "duration": 120,
    "num_of_member": 5,
    "family": true,
    "female": false
  }
]
```

### 3.2 イベント一覧取得
参加可能なイベントの一覧を取得します。

**エンドポイント**: `GET /newevent2-list/`

**レスポンス（成功時）**:
```json
[
  {
    "id": 1,
    "event_name": "岐阜ロゲイニング2025",
    "start_datetime": "2025-09-15T10:00:00Z",
    "end_datetime": "2025-09-15T16:00:00Z",
    "deadlineDateTime": "2025-09-10T23:59:59Z",
    "public": true,
    "hour_3": true,
    "hour_5": true
  }
]
```

### 3.3 イベントエントリー
チームをイベントにエントリーします。

**エンドポイント**: `POST /entry/`

**リクエストパラメータ**:
```json
{
  "team": 1,
  "event": 1,
  "category": 1,
  "date": "2025-09-15T10:00:00Z"
}
```

**レスポンス（成功時）**:
```json
{
  "id": 1,
  "team": 1,
  "event": 1,
  "category": 1,
  "zekken_number": 101,
  "date": "2025-09-15T10:00:00Z",
  "hasParticipated": false,
  "hasGoaled": false
}
```

---

## 4. ロゲイニング参加関連API

### 4.1 スタート処理
ロゲイニングのスタート処理を行います。

**エンドポイント**: `POST /start_from_rogapp`

**リクエストパラメータ**:
```json
{
  "event_code": "岐阜ロゲイニング2025",
  "team_name": "チーム名"
}
```

**レスポンス（成功時）**:
```json
{
  "status": "OK",
  "message": "スタート処理が完了しました",
  "team_name": "チーム名",
  "event_code": "岐阜ロゲイニング2025",
  "start_time": "2025-09-15 10:00:00"
}
```

**レスポンス（エラー時）**:
```json
{
  "status": "ERROR",
  "message": "指定されたチームが見つかりません"
}
```

---

## 5. チェックイン・写真撮影API

### 5.1 チェックイン登録
チェックポイント通過時のチェックイン処理を行います。

**エンドポイント**: `POST /checkin_from_rogapp`

**リクエストパラメータ**:
```json
{
  "event_code": "岐阜ロゲイニング2025",
  "team_name": "チーム名",
  "cp_number": 1,
  "image": "https://example.com/photos/checkpoint1.jpg"
}
```

**レスポンス（成功時）**:
```json
{
  "status": "OK",
  "message": "チェックポイントが正常に登録されました",
  "team_name": "チーム名",
  "cp_number": 1,
  "checkpoint_id": 123,
  "checkin_time": "2025-09-15 11:30:00",
  "point_value": 10
}
```

**レスポンス（重複エラー時）**:
```json
{
  "status": "WARNING",
  "message": "このチェックポイントは既に登録されています",
  "checkpoint_id": 123,
  "checkin_time": "2025-09-15 11:30:00"
}
```

### 5.2 チェックイン削除
誤って登録したチェックインを削除します。

**エンドポイント**: `POST /remove_checkin_from_rogapp`

**リクエストパラメータ**:
```json
{
  "event_code": "岐阜ロゲイニング2025",
  "team_name": "チーム名",
  "cp_number": 1
}
```

**レスポンス（成功時）**:
```json
{
  "status": "OK",
  "message": "チェックイン記録が削除されました",
  "cp_number": 1
}
```

---

## 6. 買い物ポイント・QRコード登録API

### 6.1 買い物ポイント写真登録
買い物ポイントでのレシート写真を登録します。

**エンドポイント**: `POST /checkin_from_rogapp`

**リクエストパラメータ**:
```json
{
  "event_code": "岐阜ロゲイニング2025",
  "team_name": "チーム名",
  "cp_number": 37,
  "image": "https://example.com/photos/receipt_37.jpg",
  "buy_flag": true
}
```

**レスポンス（成功時）**:
```json
{
  "status": "OK",
  "message": "買い物ポイントが正常に登録されました",
  "team_name": "チーム名",
  "cp_number": 37,
  "checkpoint_id": 124,
  "checkin_time": "2025-09-15 12:15:00",
  "point_value": 15
}
```

### 6.2 QRコード登録
QRコードを使用したチェックイン登録を行います。

**エンドポイント**: `POST /input_cp`

**リクエストパラメータ**:
```json
{
  "zekken_number": "101",
  "event_code": "岐阜ロゲイニング2025",
  "cp_number": 10,
  "qr_code": "QR12345ABC",
  "latitude": 35.4091,
  "longitude": 136.7581
}
```

**レスポンス（成功時）**:
```json
{
  "status": "OK",
  "message": "QRコードチェックインが完了しました",
  "cp_number": 10,
  "point_value": 10
}
```

---

## 7. ゴール・時計撮影API

### 7.1 ゴール処理
ゴール時の処理を行い、通過証明書を生成します。

**エンドポイント**: `POST /goal_from_rogapp`

**リクエストパラメータ**:
```json
{
  "event_code": "岐阜ロゲイニング2025",
  "team_name": "チーム名",
  "image": "https://example.com/photos/goal_clock.jpg",
  "goal_time": "2025-09-15 13:45:00"
}
```

**レスポンス（成功時）**:
```json
{
  "status": "OK",
  "message": "ゴール処理が正常に完了しました",
  "team_name": "チーム名",
  "goal_time": "2025-09-15 13:45:00",
  "score": 150,
  "scoreboard_url": "https://example.com/scoreboards/scoreboard_101.pdf",
  "certificate_ready": true
}
```

### 7.2 スコアボード取得
チームのスコアボード（通過証明書）を取得します。

**エンドポイント**: `GET /getScoreboard`

**リクエストパラメータ**:
```
zekken_number=101&event_code=岐阜ロゲイニング2025
```

**レスポンス（成功時）**:
- Excel形式のスコアボードファイルをダウンロード

### 7.3 スコアボードPDF取得
PDF形式のスコアボードを取得します。

**エンドポイント**: `GET /download_scoreboard`

**リクエストパラメータ**:
```
zekken_number=101&event_code=岐阜ロゲイニング2025
```

**レスポンス（成功時）**:
- PDF形式のスコアボードファイルをダウンロード

---

## 8. 証明書・印刷確認API

### 8.1 印刷状況確認
通過証明書の印刷状況を確認します。

**エンドポイント**: `GET /users/{user_id}/last-goal/`

**レスポンス（成功時）**:
```json
{
  "team_name": "チーム名",
  "goal_time": "2025-09-15T13:45:00Z",
  "score": 150,
  "certificate_printed": true,
  "print_time": "2025-09-15T13:47:00Z"
}
```

### 8.2 再印刷要求
通過証明書の再印刷を要求します。

**エンドポイント**: `POST /reprint`

**リクエストパラメータ**:
```json
{
  "zekken_number": "101",
  "event_code": "岐阜ロゲイニング2025"
}
```

**レスポンス（成功時）**:
```json
{
  "status": "OK",
  "message": "再印刷処理を開始しました",
  "estimated_print_time": "2025-09-15T14:00:00Z"
}
```

---

## 9. ユーティリティAPI

### 9.1 イベントコード確認
イベントコードの有効性を確認します。

**エンドポイント**: `POST /check_event_code`

**リクエストパラメータ**:
```json
{
  "event_code": "岐阜ロゲイニング2025"
}
```

**レスポンス（成功時）**:
```json
{
  "status": "OK",
  "event_exists": true,
  "event_name": "岐阜ロゲイニング2025",
  "start_time": "2025-09-15T10:00:00Z",
  "end_time": "2025-09-15T16:00:00Z"
}
```

### 9.2 チェックインリスト取得
チームのチェックイン履歴を取得します。

**エンドポイント**: `GET /checkins/{zekken_number}/{event_code}/`

**レスポンス（成功時）**:
```json
{
  "team_name": "チーム名",
  "zekken_number": "101",
  "checkins": [
    {
      "cp_number": 1,
      "checkin_time": "2025-09-15T11:30:00Z",
      "point_value": 10,
      "image_url": "https://example.com/photos/checkpoint1.jpg"
    },
    {
      "cp_number": 5,
      "checkin_time": "2025-09-15T12:15:00Z",
      "point_value": 15,
      "image_url": "https://example.com/photos/checkpoint5.jpg"
    }
  ],
  "total_score": 25
}
```

---

## エラーコード一覧

| ステータスコード | 説明 |
|---|---|
| 200 | 正常終了 |
| 201 | 作成成功 |
| 400 | リクエスト不正 |
| 401 | 認証エラー |
| 403 | 権限不足 |
| 404 | リソースが見つからない |
| 409 | 重複エラー |
| 500 | サーバーエラー |

## 共通エラーレスポンス

```json
{
  "status": "ERROR",
  "message": "エラーメッセージ",
  "details": "詳細な説明（省略可能）"
}
```

---

## 使用例（フロー）

### 完全なロゲイニング参加フロー

1. **ユーザー登録**
   ```bash
   curl -X POST "/register/" -d '{"email":"user@example.com","password":"pass123","firstname":"太郎","lastname":"田中"}'
   ```

2. **メール認証**
   ```bash
   curl "/verify-email/abc123def456/"
   ```

3. **ログイン**
   ```bash
   curl -X POST "/login/" -d '{"identifier":"user@example.com","password":"pass123"}'
   ```

4. **チーム作成**
   ```bash
   curl -X POST "/teams/" -H "Authorization: Token <token>" -d '{"team_name":"サンプルチーム","category":1}'
   ```

5. **メンバー追加**
   ```bash
   curl -X POST "/teams/1/members/" -H "Authorization: Token <token>" -d '{"email":"member@example.com","firstname":"花子","lastname":"佐藤"}'
   ```

6. **イベントエントリー**
   ```bash
   curl -X POST "/entry/" -H "Authorization: Token <token>" -d '{"team":1,"event":1,"category":1}'
   ```

7. **スタート**
   ```bash
   curl -X POST "/start_from_rogapp" -d '{"event_code":"岐阜ロゲイニング2025","team_name":"サンプルチーム"}'
   ```

8. **チェックイン**
   ```bash
   curl -X POST "/checkin_from_rogapp" -d '{"event_code":"岐阜ロゲイニング2025","team_name":"サンプルチーム","cp_number":1,"image":"https://example.com/photo1.jpg"}'
   ```

9. **ゴール**
   ```bash
   curl -X POST "/goal_from_rogapp" -d '{"event_code":"岐阜ロゲイニング2025","team_name":"サンプルチーム","image":"https://example.com/goal.jpg"}'
   ```

10. **証明書取得**
    ```bash
    curl "/download_scoreboard?zekken_number=101&event_code=岐阜ロゲイニング2025"
    ```

---

## 自動証明書生成について

ゴール処理（`goal_from_rogapp`）が完了すると、システムは自動的に以下を実行します：

1. **スコア計算**: チェックポイントの獲得ポイントとタイムペナルティを計算
2. **証明書生成**: Excel/PDF形式のスコアボード（通過証明書）を生成
3. **自動印刷**: 設定されている場合、自動印刷システムが証明書を印刷
4. **クラウド保存**: 生成された証明書をAWS S3などのクラウドストレージに保存
5. **印刷確認**: 印刷完了の確認とログ記録

この一連の処理により、ゴール後すぐに通過証明書が生成・印刷され、参加者に提供されます。

---

## 注意事項

1. **認証トークンの管理**: セキュリティのため、適切にトークンを管理してください
2. **レート制限**: 過度なリクエストを避けるため、適切な間隔でAPIを呼び出してください
3. **画像アップロード**: 画像ファイルは事前に適切なストレージにアップロードし、URLを指定してください
4. **時刻形式**: すべての時刻は ISO 8601 形式（YYYY-MM-DDTHH:MM:SSZ）で指定してください
5. **エラーハンドリング**: APIからのエラーレスポンスを適切に処理してください

---

## データベーステーブル使用状況

### 各API機能でのテーブル操作詳細

#### 1. 認証系API
**`/check_event_code`**
- **参照**: `rog_newevent2` (イベント存在確認)
- **参照**: `rog_entry` (チーム認証・パスワード確認)

#### 2. チェックイン系API
**`/input_cp` (チェックイン登録)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_entry` (チーム情報取得)
- **参照**: `rog_gpslog` (重複チェックイン確認)
- **作成**: `rog_gpslog` (新規チェックイン記録)
- **参照**: `rog_location2025` (チェックポイント得点情報)

**`/goal_from_rogapp` (ゴール登録)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_entry` (チーム情報取得)
- **参照**: `rog_gpslog` (スコア計算用チェックイン履歴)
- **参照**: `rog_location2025` (チェックポイント得点情報)
- **更新**: `rog_entry` (ゴール時刻・スコア更新)

#### 3. チーム情報系API
**`/get_teams` (チーム一覧)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_entry` (チーム基本情報)
- **参照**: `rog_gpslog` (チェックイン数集計)
- **参照**: `rog_customuser` (オーナー情報)

#### 4. ランキング系API
**`/current_ranking` (現在ランキング)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_entry` (チーム情報・スコア・ゴール情報)
- **参照**: `rog_gpslog` (チェックポイント通過数)
- **参照**: `rog_customuser` (オーナー情報)

#### 5. 位置情報系API
**`/get_waypoint_datas_from_rogapp` (ウェイポイント投稿)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_entry` (チーム情報取得)
- **参照**: `rog_waypoint` (重複チェック)
- **作成**: `rog_waypoint` (GPS軌跡データ保存)

**`/get_route` (ルート情報取得)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_entry` (チーム情報取得)
- **参照**: `rog_waypoint` (GPS軌跡履歴)
- **参照**: `rog_gpslog` (チェックイン履歴)
- **参照**: `rog_location2025` (チェックポイント座標情報)

#### 6. チェックポイント情報系API
**`/get_checkpoints` (チェックポイント一覧)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_location2025` (チェックポイント詳細情報)

#### 7. 編集系API
**`/remove_checkin_from_rogapp` (チェックイン削除)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_entry` (チーム情報取得)
- **参照**: `rog_gpslog` (削除対象チェックイン検索)
- **削除**: `rog_gpslog` (チェックイン記録削除)

**`/get_checkin_list` (チェックイン履歴)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_entry` (チーム情報取得)
- **参照**: `rog_gpslog` (チェックイン履歴取得)
- **参照**: `rog_location2025` (チェックポイント詳細情報)

#### 8. 写真・メディア系API
**`/get_photo_list` (写真一覧)**
- **参照**: `rog_newevent2` (イベント情報取得)
- **参照**: `rog_entry` (チーム情報取得)
- **参照**: `rog_gpslog` (チェックイン画像URL)

---

## テーブル別API使用一覧表

### 🎯 コアテーブル（全APIで使用）

| テーブル名 | 参照API | 作成API | 更新API | 削除API | 役割 |
|-----------|---------|---------|---------|---------|------|
| `rog_newevent2` | 全API | - | - | - | イベント基本情報・認証基盤 |
| `rog_entry` | 全API | - | goal_from_rogapp | - | チーム基本情報・スコア管理 |

### 📍 GPS・位置情報系テーブル

| テーブル名 | 参照API | 作成API | 更新API | 削除API | 役割 |
|-----------|---------|---------|---------|---------|------|
| `rog_gpslog` | input_cp, goal_from_rogapp, get_teams, current_ranking, get_checkin_list, get_photo_list | input_cp | - | remove_checkin_from_rogapp | チェックイン記録管理 |
| `rog_location2025` | input_cp, goal_from_rogapp, get_checkpoints, get_route, get_checkin_list | - | - | - | チェックポイント座標・得点情報 |
| `rog_waypoint` | get_waypoint_datas_from_rogapp, get_route | get_waypoint_datas_from_rogapp | - | - | GPS軌跡データ |

### 👥 ユーザー・認証系テーブル

| テーブル名 | 参照API | 作成API | 更新API | 削除API | 役割 |
|-----------|---------|---------|---------|---------|------|
| `rog_customuser` | get_teams, current_ranking | - | - | - | ユーザー基本情報・オーナー情報 |
| `knox_authtoken` | 認証が必要な全API | ログイン時 | - | ログアウト時 | API認証トークン管理 |

### 📊 集計・分析系テーブル（読み取り専用）

| テーブル名 | 参照API | 役割 |
|-----------|---------|------|
| `v_category_rankings` | current_ranking | カテゴリ別ランキング集計ビュー |
| `v_checkin_summary` | get_checkin_list | チェックイン集計ビュー |
| `mv_entry_details` | get_teams | エントリー詳細マテリアライズドビュー |

### 🖼️ メディア・画像系テーブル

| テーブル名 | 参照API | 作成API | 役割 |
|-----------|---------|---------|------|
| `rog_checkinimages` | get_photo_list | input_cp | チェックイン時の写真 |
| `rog_goalimages` | get_photo_list | goal_from_rogapp | ゴール時の写真 |

---

## 重複・非推奨テーブルについて

### 🔄 移行中の重複テーブル

#### GPS情報関連
- **`gps_information`** (移行元・13,550件): MobServerからの旧GPS記録
- **`rog_gpslog`** (移行先・0件): Django管理の新GPS記録
- **状況**: データ移行が未完了、現在は`gps_information`を直接参照

#### イベント管理関連
- **`rog_newevent`** (旧): 初期バージョンのイベントモデル
- **`rog_newevent2`** (現行): 拡張されたイベントモデル（API推奨）
- **推奨**: 新規開発では`rog_newevent2`を使用

#### カテゴリ管理関連
- **`rog_category`** (旧): 旧カテゴリシステム
- **`rog_newcategory`** (現行): 新カテゴリシステム
- **推奨**: 新規開発では`rog_newcategory`を使用

### 🗑️ 将来的に不要になるテーブル

#### 一時・作業用テーブル
- **`tmp_checkin`**: チェックイン一時テーブル（作業完了後削除予定）
- **`tmp_checkpont_summary`**: チェックポイント集計作業用
- **`tmp_goalimage`**: ゴール画像一時テーブル
- **`tmp_point`**: ポイント一時テーブル
- **`tmp_team_table`**: チームテーブル作業用
- **`temp_gifuroge_team`**: ぎふロゲチーム一時データ

#### バックアップテーブル
- **`gps_checkins_backup`**: GPSチェックインバックアップ
- **`django_migrations_backup`**: マイグレーションバックアップ

#### 開発・テスト用テーブル
- **`rog_testmodel`**: 開発テスト用（本番環境では不要）

### 📋 無効化されているテーブル

#### 将来機能（当面無効）
- **`rog_chatlog`**: LINE Bot機能（`managed = False`）
- **`rog_chatstatus`**: チャット状態管理（`managed = False`）
- **`rog_agentflag`**: エージェント機能（`managed = False`）
- **`rog_agentlogin`**: エージェントログイン（`managed = False`）

これらのテーブルは将来的な機能拡張のために定義されていますが、現在は無効化されています。

---

## テーブル使用頻度とパフォーマンス考慮事項

### 🔥 高頻度アクセステーブル
1. **`rog_newevent2`**: 全APIで必須（キャッシュ推奨）
2. **`rog_entry`**: 全APIで必須（インデックス最適化済み）
3. **`rog_gpslog`**: GPS関連APIで重要（空間インデックス推奨）

### ⚡ 最適化されているテーブル
- **`rog_location2025`**: PostGIS空間インデックス、CSV一括アップロード機能
- **`rog_gpslog`**: 複合インデックス（zekken_number + event_code）
- **`mv_entry_details`**: マテリアライズドビュー（高速集計）

### 📈 将来的なスケーリング考慮
- GPS軌跡データ（`rog_waypoint`）の分割・アーカイブ戦略
- 画像データの外部ストレージ移行
- ランキング計算の非同期処理化

---

## 🆕 Location2025移行による拡張機能

### CSVベースチェックポイント管理
2025年8月実装のLocation2025により、従来のlocationテーブルから大幅に機能拡張されました：

#### 新機能
- **CSV一括アップロード**: Django管理画面でチェックポイント定義の一括インポート
- **CSV一括ダウンロード**: 現在のチェックポイント設定の一括エクスポート
- **空間データ統合**: 緯度経度とPointFieldの自動同期
- **イベント連携強化**: rog_newevent2との外部キー制約

#### CSV形式仕様
```csv
cp_number,event_code,cp_name,latitude,longitude,point_value,description,image_path,buy_flag
1,岐阜ロゲイニング2025,市役所,35.4091,136.7581,10,スタート/ゴール地点,,false
2,岐阜ロゲイニング2025,岐阜公園,35.4122,136.7514,15,信長居館跡,,false
```

#### API拡張
- 全チェックポイント関連APIが新テーブル`rog_location2025`を参照
- 管理機能の向上によりリアルタイムでのチェックポイント設定変更が可能
- PostGIS空間検索機能の継続利用

#### 移行状況
- **完了**: モデル定義、管理画面、CSV機能、API更新
- **対象API**: `/get_checkpoints`, `/input_cp`, `/goal_from_rogapp`, `/get_route`, `/get_checkin_list`
- **後方互換性**: 既存のlocationテーブルは維持（必要に応じて参照可能）

---

本仕様書に記載されていない詳細については、システム管理者にお問い合わせください。

---

## 🆕 管理者向けAPI (2025年8月追加)

### 一括写真アップロード機能

#### POST /bulk-upload-photos/
複数の写真を一括でアップロードし、EXIF情報から自動的にチェックイン処理を行います。

**認証**: 管理者権限必須

**リクエスト**:
```http
POST /api/bulk-upload-photos/
Content-Type: multipart/form-data
Authorization: Token <admin_token>

event_code: 岐阜2412
photos: [file1.jpg, file2.jpg, file3.jpg, ...]
```

**レスポンス（成功時）**:
```json
{
  "success": true,
  "processed_count": 15,
  "success_count": 12,
  "failed_count": 3,
  "results": [
    {
      "filename": "photo001.jpg",
      "status": "success",
      "checkin_id": 1234,
      "gps": {"lat": 35.4091, "lon": 136.7581},
      "timestamp": "2025-08-24T14:30:00Z"
    },
    {
      "filename": "photo002.jpg",
      "status": "failed",
      "error": "GPS情報が見つかりません"
    }
  ]
}
```

**処理内容**:
1. アップロードされた写真からEXIF情報を抽出
2. GPS座標と撮影時刻を取得
3. 近接するチェックポイントを検索
4. 自動的にチェックイン処理を実行
5. validation_status: 'AUTO_APPROVED'で記録

---

### 通過審査管理機能

#### POST /confirm-checkin-validation/
チェックインの確定・否認処理を行います。

**認証**: 管理者権限必須

**リクエスト**:
```json
{
  "checkin_id": 1234,
  "action": "APPROVED",
  "comment": "写真確認により承認"
}
```

**actionの値**:
- `APPROVED`: 承認
- `REJECTED`: 却下

**レスポンス（成功時）**:
```json
{
  "success": true,
  "checkin_id": 1234,
  "new_status": "APPROVED",
  "validated_at": "2025-08-24T15:30:00Z",
  "validated_by": "admin@example.com"
}
```

---

### 全参加者ランキング表示

#### GET /event-participants-ranking/
イベント全参加者の得点と確定状況をクラス別降順で取得します。

**認証**: 管理者権限必須

**パラメータ**:
- `event_code`: イベントコード（必須）

**リクエスト例**:
```http
GET /api/event-participants-ranking/?event_code=岐阜2412
Authorization: Token <admin_token>
```

**レスポンス**:
```json
{
  "event_code": "岐阜2412",
  "event_name": "岐阜ロゲイニング2024年12月大会",
  "participants": [
    {
      "zekken_number": "001",
      "team_name": "チーム岐阜",
      "class_name": "一般男子",
      "confirmed_points": 150,
      "pending_points": 30,
      "total_checkins": 12,
      "confirmed_checkins": 10,
      "members": ["田中太郎", "佐藤次郎"]
    },
    {
      "zekken_number": "002",
      "team_name": "スピードランナーズ",
      "class_name": "一般男子",
      "confirmed_points": 140,
      "pending_points": 0,
      "total_checkins": 9,
      "confirmed_checkins": 9,
      "members": ["山田三郎", "鈴木四郎"]
    }
  ]
}
```

---

### 参加者詳細審査情報

#### GET /participant-validation-details/
特定参加者の詳細な審査状況を取得します。

**認証**: 管理者権限必須

**パラメータ**:
- `zekken_number`: ゼッケン番号（必須）
- `event_code`: イベントコード（必須）

**リクエスト例**:
```http
GET /api/participant-validation-details/?zekken_number=001&event_code=岐阜2412
Authorization: Token <admin_token>
```

**レスポンス**:
```json
{
  "team_info": {
    "zekken_number": "001",
    "team_name": "チーム岐阜",
    "class_name": "一般男子",
    "members": ["田中太郎", "佐藤次郎"]
  },
  "checkins": [
    {
      "id": 1234,
      "cp_number": 5,
      "location_name": "岐阜公園",
      "checkin_time": "2025-08-24T14:30:00Z",
      "validation_status": "APPROVED",
      "validation_comment": "写真確認により承認",
      "validated_at": "2025-08-24T15:30:00Z",
      "validated_by": "admin@example.com",
      "points": 15,
      "photo_url": "/media/checkin_photos/photo001.jpg"
    }
  ],
  "summary": {
    "total_points": 180,
    "confirmed_points": 150,
    "pending_points": 30,
    "rejected_points": 0
  }
}
```

---

### イベント参加者一覧

#### GET /event-zekken-list/
指定イベントの全参加者ゼッケン番号一覧を取得します。

**認証**: 管理者権限必須

**パラメータ**:
- `event_code`: イベントコード（必須）

**リクエスト例**:
```http
GET /api/event-zekken-list/?event_code=岐阜2412
Authorization: Token <admin_token>
```

**レスポンス**:
```json
{
  "event_code": "岐阜2412",
  "participants": [
    {
      "zekken_number": "ALL",
      "team_name": "全参加者表示",
      "is_all_option": true
    },
    {
      "zekken_number": "001",
      "team_name": "チーム岐阜",
      "class_name": "一般男子",
      "is_all_option": false
    },
    {
      "zekken_number": "002", 
      "team_name": "スピードランナーズ",
      "class_name": "一般男子",
      "is_all_option": false
    }
  ]
}
```

---

### 管理者向けAPI利用時の注意事項

1. **認証レベル**: すべての管理者向けAPIは管理者権限（is_superuser=True）が必要
2. **レート制限**: 一括アップロードは1回あたり最大100ファイルまで
3. **ファイルサイズ**: 1ファイルあたり最大10MB
4. **対応形式**: JPEG, PNG (EXIF情報が含まれる写真のみ自動処理対象)
5. **エラーハンドリング**: 部分的な失敗でも成功した分は処理されます
6. **ログ**: すべての管理者操作は詳細ログが記録されます

---
