29 KiB
29 KiB
統合移行操作手順書
最終更新: 2025年8月24日
移行結果: ✅ 移行完了 - GPS移行成功、Location2025移行7,601/7,740件完了(98.2%)、画像パスS3移行51,651件完了(100%)
拡張結果: ✅ 実装完了 - Location2025機能完全利用可能(完了実績版)
📋 概要
gifuroge(MobServer)からrogdb(Django)への過去GPSデータ移行、Location2025 チェックポイント管理システム拡張、および過去画像データのS3パス統一化の実施が必要な状況
対象システム: ロゲイニング過去データ移行 + Location2025拡張 + 画像パスS3移行
現在の状況: ✅ 移行完了 - GPS移行完了済み、Location2025移行ほぼ完了(98.2%)、画像パスS3移行完了(100%)
版数: v4.2(画像移行完了版)
移行結果: ✅ 完了 - GPS移行成功、Location2025移行7,601/7,740件完了、画像パスS3移行51,651件完了
拡張結果: ✅ 完全実装 - Location2025機能完全利用可能、S3画像パス統一完了
📊 実施済み移行と追加課題
✅ 成功済み移行状況
- GPSデータ移行完了: 12,665件のGPSデータが
rog_gpscheckinテーブルに正常移行済み - Location2025移行完了: 7,601件(98.2%)がLocation2025に移行済み
- 高山2イベント: 7,502件の新規移行 + 99件の既存データ
- エラー: 139件(座標データNull)
- 画像パスS3移行完了: 51,651件(100%)がS3形式パスに移行済み
- ゴール画像: 22,147件
- チェックイン画像: 29,504件
- 移行時間: 1分4秒で完了
- API完全稼働: get_checkpoint_list APIが全イベントで動作可能
⚠️ 残存課題
- Location2025完全移行: ✅ 完了 - 7,601件移行済み(7,740件中、移行率98.2%)
- 座標データ修正: 139件のエラー(座標データがNullのもの)
- ドキュメント修正: GPS移行成功を正しいテーブル名(rog_gpscheckin)で反映
- 既存データ保護継続: 188件の本番entryデータ保護維持
🔧 成功した移行手順
Phase 1: データ分析と問題特定(実施済み)
1.1 汚染データの発見
-- 写真記録の汚染データ発見クエリ
SELECT record_time, COUNT(*)
FROM gps_information
WHERE serial_number >= 20000
AND DATE(record_time) = '2023-05-24'
GROUP BY record_time;
-- 結果: 2,136件のテストデータ汚染を確認
1.2 GPS専用データの特定
-- 信頼できるGPSデータの確認
SELECT COUNT(*) FROM gps_information
WHERE serial_number < 20000;
-- 結果: 12,665件の有効なGPSデータを確認
Phase 2: 既存データ保護版移行実装(2025年8月22日更新)
2.1 既存データ保護版移行プログラム(migration_data_protection.py)
⚠️ 重要: 従来のmigration_final_simple.pyは既存データを削除するため使用禁止
def backup_existing_data(target_cursor):
"""既存データのバックアップ状況を確認"""
# 既存データ数を確認
target_cursor.execute("SELECT COUNT(*) FROM rog_entry")
entry_count = target_cursor.fetchone()[0]
target_cursor.execute("SELECT COUNT(*) FROM rog_team")
team_count = target_cursor.fetchone()[0]
target_cursor.execute("SELECT COUNT(*) FROM rog_member")
member_count = target_cursor.fetchone()[0]
if entry_count > 0 or team_count > 0 or member_count > 0:
print("✅ 既存のcore application dataが検出されました。これらは保護されます。")
return True
else:
print("⚠️ 既存のcore application dataが見つかりません。")
return False
def clean_target_database_selective(target_cursor):
"""選択的クリーンアップ(既存データを保護)"""
# GPSチェックインデータのみクリーンアップ(重複移行防止)
target_cursor.execute("DELETE FROM rog_gpscheckin WHERE comment = 'migrated_from_gifuroge'")
# 注意: rog_entry, rog_team, rog_member は削除しない!
2.2 GPS専用データ移行処理
# GPS専用データ取得(serial_number < 20000)
source_cur.execute("""
SELECT
serial_number, team_name, cp_number, record_time,
goal_time, late_point, buy_flag, image_address,
minus_photo_flag, create_user, update_user,
colabo_company_memo
FROM gps_information
WHERE serial_number < 20000 -- GPS専用データのみ
ORDER BY serial_number
""")
gps_records = source_cur.fetchall()
for record in gps_records:
# UTC → JST 変換
if record[3]: # record_time
utc_time = record[3].replace(tzinfo=pytz.UTC)
jst_time = utc_time.astimezone(pytz.timezone('Asia/Tokyo'))
checkin_time = jst_time.strftime('%Y-%m-%d %H:%M:%S')
# rog_gpscheckin テーブルに挿入(マイグレーション識別マーカー付き)
target_cur.execute("""
INSERT INTO rog_gpscheckin
(serial_number, team_name, cp_number, record_time, goal_time,
late_point, buy_flag, image_address, minus_photo_flag,
create_user, update_user, comment)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
""", (
serial_number, team_name, cp_number, record_time_jst, goal_time_utc,
late_point, buy_flag, image_address, minus_photo_flag,
create_user, update_user, 'migrated_from_gifuroge' # 移行識別マーカー
))
### Phase 3: 既存データ保護手順(2025年8月22日追加)
#### 3.1 移行前の既存データ確認
```bash
# 既存のcore application dataの確認
docker compose exec postgres-db psql -h localhost -p 5432 -U admin -d rogdb -c "
SELECT
'rog_entry' as table_name, COUNT(*) as count FROM rog_entry
UNION ALL
SELECT
'rog_team' as table_name, COUNT(*) as count FROM rog_team
UNION ALL
SELECT
'rog_member' as table_name, COUNT(*) as count FROM rog_member;
"
# 期待される結果(バックアップデータが復元されている場合):
# table_name | count
# ------------+-------
# rog_entry | 243
# rog_team | 215
# rog_member | 259
3.2 バックアップからのデータ復元(必要な場合)
# 方法1: 専用復元スクリプトを使用(推奨)
docker compose exec app python restore_core_data.py
# 実行結果例:
# ✅ 復元成功: Entry 243件, Team 215件復元
# 🎉 コアデータ復元完了
# supervisor画面でゼッケン番号候補が表示されるようになります
# 方法2: 手動復元(バックアップ全体)
docker compose exec postgres-db psql -h localhost -p 5432 -U admin -d rogdb < testdb/rogdb.sql
# 復元後の確認
docker compose exec postgres-db psql -h localhost -p 5432 -U admin -d rogdb -c "
SELECT COUNT(*) as restored_entries FROM rog_entry;
SELECT COUNT(*) as restored_teams FROM rog_team;
SELECT COUNT(*) as restored_members FROM rog_member;
"
3.3 既存データ保護版移行実行
# 既存データを保護しながらGPSデータのみ移行
docker compose exec app python migration_data_protection.py
# 実行結果例:
# ✅ 既存のentry、team、memberデータは保護されました
# ✅ GPS専用データ移行完了: 12,665件
# ✅ タイムゾーン変換成功: UTC → JST
Phase 4: 旧版移行手順(使用禁止)
4.1 危険な旧版移行コマンド(使用禁止)
# ❌ 使用禁止: 既存データを削除してしまう
docker compose exec app python migration_final_simple.py
# この実行により既存のentry、team、memberデータが削除される!
Phase 5: 成功実績(参考)
3.1 移行コマンド実行
# データ移行実行(本番用)
docker compose exec -e PGPASSWORD=admin123456 app \
python manage.py migrate_mobserver_data \
--batch-size 100 \
--host postgres-db \
--port 5432 \
--database gifuroge \
--user admin
3.2 移行進捗モニタリング
# 移行中のデータ件数確認
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
SELECT
'イベント' as テーブル, COUNT(*) as 件数 FROM rog_newevent2
UNION ALL
SELECT 'チーム', COUNT(*) FROM rog_team
UNION ALL
SELECT 'チェックポイント', COUNT(*) FROM rog_checkpoint
UNION ALL
SELECT 'GPS位置情報', COUNT(*) FROM rog_gpscheckin;
"
Step 4: データ整合性チェック
4.1 データ件数確認
# MobServerの元データ件数
docker compose exec -e PGPASSWORD=admin123456 postgres-db \
psql -h localhost -U admin -d gifuroge -c "
SELECT
'イベント(元)' as テーブル, COUNT(*) FROM event_table
UNION ALL
SELECT 'チーム(元)', COUNT(*) FROM team_table
UNION ALL
SELECT 'チェックポイント(元)', COUNT(*) FROM checkpoint_table
UNION ALL
SELECT 'GPS情報(元)', COUNT(*) FROM gps_information;
"
# 統合後データ件数確認
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
SELECT
'イベント(統合)' as テーブル, COUNT(*) FROM rog_newevent2
UNION ALL
SELECT 'チーム(統合)', COUNT(*) FROM rog_team
UNION ALL
SELECT 'チェックポイント(統合)', COUNT(*) FROM rog_checkpoint
UNION ALL
SELECT 'GPS位置情報(統合)', COUNT(*) FROM rog_gpscheckin;
"
4.2 データ関連性チェック
# 外部キー関連性確認
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
-- チーム-イベント関連確認
SELECT
COUNT(*) as 関連済みチーム数,
COUNT(CASE WHEN event_id IS NULL THEN 1 END) as 関連なしチーム数
FROM rog_team;
-- GPS-チーム関連確認
SELECT
COUNT(*) as GPS総数,
COUNT(CASE WHEN team_id IS NOT NULL THEN 1 END) as チーム関連済みGPS,
COUNT(CASE WHEN checkpoint_id IS NOT NULL THEN 1 END) as CP関連済みGPS
FROM rog_gpscheckin;
"
4.3 PostGIS空間データ確認
# 空間データの整合性確認
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
-- チェックポイント位置データ確認
SELECT
COUNT(*) as 総CP数,
COUNT(CASE WHEN location IS NOT NULL THEN 1 END) as 位置情報ありCP数,
COUNT(CASE WHEN ST_IsValid(location) THEN 1 END) as 有効位置情報数
FROM rog_checkpoint;
-- チーム位置データ確認
SELECT
COUNT(*) as 総チーム数,
COUNT(CASE WHEN location IS NOT NULL THEN 1 END) as 位置情報ありチーム数
FROM rog_team;
"
Step 5: アプリケーション動作確認
5.1 Django管理画面確認
# Django管理画面サーバー起動
python manage.py runserver 0.0.0.0:8000
# 確認項目:
# - イベント一覧表示
# - チーム一覧表示
# - チェックポイント一覧表示
# - GPS位置情報一覧表示
# - 地図表示機能
5.2 API動作確認
# REST API動作確認
curl -X GET "http://localhost:8000/api/events/" -H "Accept: application/json"
curl -X GET "http://localhost:8000/api/teams/" -H "Accept: application/json"
curl -X GET "http://localhost:8000/api/checkpoints/" -H "Accept: application/json"
curl -X GET "http://localhost:8000/api/gps-checkins/" -H "Accept: application/json"
Step 6: 性能テスト
6.1 データベースインデックス確認
# インデックス使用状況確認
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
-- チーム関連インデックス
EXPLAIN ANALYZE SELECT * FROM rog_team WHERE zekken_number = '1001';
-- チェックポイント空間インデックス
EXPLAIN ANALYZE SELECT * FROM rog_checkpoint
WHERE ST_DWithin(location, ST_GeomFromText('POINT(136.0 35.0)', 4326), 1000);
-- GPS時系列インデックス
EXPLAIN ANALYZE SELECT * FROM rog_gpscheckin
WHERE checkin_time >= '2023-01-01' ORDER BY checkin_time;
"
🚨 ロールバック手順
緊急時ロールバック
# 1. サービス停止
docker compose down
# 2. データベースリストア
docker compose exec postgres-db psql -h localhost -U admin -d rogdb \
< django_data_backup_YYYYMMDD_HHMMSS.sql
# 3. Djangoマイグレーション戻し
python manage.py migrate rog 0003_previous_migration
# 4. サービス再開
docker compose up -d
📊 移行完了チェックリスト
データ移行完了確認
- イベントデータ: 元データ件数と統合後件数の整合性
- チームデータ: ゼッケン番号とイベントコードの関連性
- チェックポイントデータ: 位置情報の正確性
- GPS位置情報: 時系列データの連続性
機能動作確認
- Django管理画面: 全テーブルの表示・編集
- REST API: GET/POST/PUT/DELETE操作
- 地図機能: PostGIS空間クエリ動作
- 検索機能: インデックス使用確認
性能確認
- レスポンス時間: API応答時間 < 2秒
- 同時接続: 100ユーザー同時アクセス対応
- データベースアクセス: インデックス効率化確認
📈 監視項目
移行中監視
# CPU・メモリ使用率監視
docker stats
# データベース接続数監視
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
SELECT count(*) as active_connections
FROM pg_stat_activity
WHERE state = 'active';
"
# ディスク使用量監視
df -h
移行後継続監視
- データベースサイズ増加率
- API応答時間
- エラーログ件数
- 同時接続ユーザー数
🔧 トラブルシューティング
よくある問題と対処法
1. マイグレーション失敗
# 現在のマイグレーション状態確認
python manage.py showmigrations rog
# fake適用でマイグレーション修正
python manage.py migrate rog 0005_create_gps_tables --fake
2. データ移行タイムアウト
# バッチサイズを削減して再実行
python manage.py migrate_mobserver_data --batch-size 50
3. PostGIS空間データエラー
# 空間データの修復
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
UPDATE rog_checkpoint SET location = ST_SetSRID(location, 4326)
WHERE ST_SRID(location) = 0;
"
4. 外部キー制約エラー
# 制約確認と修復
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
-- 孤立データ確認
SELECT COUNT(*) FROM rog_team WHERE event_id NOT IN (SELECT id FROM rog_newevent2);
-- 孤立データクリーンアップ
DELETE FROM rog_team WHERE event_id NOT IN (SELECT id FROM rog_newevent2);
"
📋 移行完了報告書テンプレート
移行実施結果
実施日時: YYYY/MM/DD HH:MM - HH:MM
実施者: [担当者名]
移行時間: X時間Y分
データ移行結果
| テーブル | 移行前件数 | 移行後件数 | 状況 |
|---|---|---|---|
| イベント | XX件 | XX件 | ✅ |
| チーム | XX件 | XX件 | ✅ |
| チェックポイント(location2025) | XX件 | XX件 | ✅ |
| GPS位置情報 | XX件 | XX件 | ✅ |
発生した問題と対処
- 問題: [問題内容] 対処: [対処内容] 結果: [解決済み/継続監視]
移行後確認項目
- 管理画面動作確認
- Location2025 CSV機能確認
- API動作確認
- 地図機能確認
- 性能確認
🆕 Location2025拡張機能移行手順(2025年8月追加)
Phase 4: Location2025システム導入
4.1 事前準備
# Location2025テーブル作成
docker compose exec app python manage.py makemigrations
docker compose exec app python manage.py migrate
# 管理者権限確認
docker compose exec app python manage.py shell
>>> from django.contrib.auth.models import User
>>> User.objects.filter(is_superuser=True).count()
4.2 Location2025機能検証
# Django Admin アクセス確認
curl -I http://localhost:8000/admin/
# CSV機能テスト
# 1. 管理画面でLocation2025セクションにアクセス
# 2. "CSV一括アップロード"機能をテスト
# 3. サンプルCSVファイルでデータ投入確認
# 4. "CSV一括ダウンロード"機能をテスト
4.3 API移行確認
# チェックポイント関連API動作確認
curl -X GET "http://localhost:8000/api/get_checkpoints?event_code=テストイベント"
# 移行されたAPI関数の動作確認
docker compose exec app python manage.py shell
>>> from rog.views_apis.api_events import *
>>> from rog.views_apis.api_play import *
# Location2025参照になっていることを確認
4.4 空間データ機能確認
# PostGIS機能確認
docker compose exec db psql -U postgres -d rogdb -c "
SELECT cp_name, ST_AsText(location)
FROM rog_location2025
WHERE location IS NOT NULL
LIMIT 5;"
# 空間インデックス確認
docker compose exec db psql -U postgres -d rogdb -c "
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'rog_location2025';"
Phase 5: データ品質確認とメンテナンス
5.1 Location2025データ整合性確認
-- 重複チェック
SELECT event_id, cp_number, COUNT(*) as cnt
FROM rog_location2025
GROUP BY event_id, cp_number
HAVING COUNT(*) > 1;
-- 座標値検証(日本国内範囲)
SELECT COUNT(*) FROM rog_location2025
WHERE latitude NOT BETWEEN 24 AND 46
OR longitude NOT BETWEEN 123 AND 146;
-- 空間データ同期確認
SELECT COUNT(*) FROM rog_location2025
WHERE location IS NULL
AND latitude IS NOT NULL
AND longitude IS NOT NULL;
5.2 パフォーマンス最適化
# インデックス使用状況確認
docker compose exec db psql -U postgres -d rogdb -c "
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
WHERE tablename = 'rog_location2025';"
# テーブル統計更新
docker compose exec db psql -U postgres -d rogdb -c "
ANALYZE rog_location2025;"
🖼️ 画像パスS3移行手順(2025年8月追加)
Phase 6: 過去画像データのS3パス統一化
6.1 事前準備と現状確認
# 現在の画像データ状況確認
docker compose exec app python manage.py shell -c "
from rog.models import GoalImage, CheckinImage
print(f'ゴール画像: {GoalImage.objects.count()}件')
print(f'チェックイン画像: {CheckinImage.objects.count()}件')
print(f'総画像数: {GoalImage.objects.count() + CheckinImage.objects.count()}件')
"
6.2 パス変換プレビュー
# 実際の変換を実行する前にプレビュー確認
docker compose exec app python preview_path_conversion.py
# 期待される出力例:
# ✅ GoalImage ID=1: goals/230205/2269a407-3745-44fc-977d-f0f22bda112f.jpg
# -> s3://sumasenrogaining/各務原/goals/kagamigaharaTest2/2269a407-3745-44fc-977d-f0f22bda112f.jpg (90文字)
6.3 本格実行
# 画像パスのS3形式への更新実行
docker compose exec app python run_path_update.py
# 実行時のログ出力:
# 🐳 Docker環境でデータベースパス更新を実行します...
# 🚀 データベースのパス情報をS3形式に更新します...
# INFO バックアップ完了: path_update_backup_YYYYMMDD_HHMMSS.json
# INFO === GoalImagesのパス更新開始 ===
# INFO 更新対象GoalImages: XXXXX件
# INFO ✅ GoalImage ID=X: [変換ログ]
# INFO === CheckinImagesのパス更新開始 ===
# INFO 更新対象CheckinImages: XXXXX件
# INFO ✅ CheckinImage ID=X: [変換ログ]
6.4 移行結果確認
# 移行完了後の確認
docker compose exec app python manage.py shell -c "
from rog.models import GoalImage, CheckinImage
import re
# S3パスに変換済みの件数確認
s3_goals = GoalImage.objects.filter(image__startswith='s3://').count()
s3_checkins = CheckinImage.objects.filter(image__startswith='s3://').count()
print(f'S3形式のゴール画像: {s3_goals}件')
print(f'S3形式のチェックイン画像: {s3_checkins}件')
print(f'S3形式総数: {s3_goals + s3_checkins}件')
# サンプル確認
print('\n--- サンプルパス確認 ---')
for img in GoalImage.objects.filter(image__startswith='s3://')[:3]:
print(f'GoalImage: {img.image} ({len(img.image)}文字)')
for img in CheckinImage.objects.filter(image__startswith='s3://')[:3]:
print(f'CheckinImage: {img.image} ({len(img.image)}文字)')
"
6.5 バックアップとロールバック準備
# バックアップファイルの確認
ls -la path_update_backup_*.json
ls -la path_update_report_*.json
# 必要に応じてロールバック実行
# docker compose exec app python rollback_image_paths.py
✅ 画像移行実績(2025年8月24日完了)
- 総処理件数: 51,651件(100%成功)
- ゴール画像: 22,147件
- チェックイン画像: 29,504件
- 更新時間: 約1分4秒で完了
- 100文字制限対応: 全件がDjangoの制限内(78-90文字範囲)
- バックアップ: 更新前データ完全保存済み
- URL形式:
s3://sumasenrogaining/{イベントコード}/goals/{チーム名}/{ファイル名}s3://sumasenrogaining/{イベントコード}/{チーム名}/{ファイル名}
🎉 最終移行結果(2025-01-24完了)
✅ 移行完了実績
| 項目 | ソーステーブル | ターゲットテーブル | 移行件数 | 成功率 |
|---|---|---|---|---|
| GPSデータ移行 | gps_information | rog_gpscheckin | 12,665件 | 100% |
| Location2025移行 | rog_location | rog_location2025 | 7,601件 / 7,740件 | 98.2% |
| 画像パスS3移行 | ローカルパス | S3プロトコルパス | 51,651件 | 100% |
🎯 Location2025移行詳細
- 新規移行: 7,502件(高山2イベントとして一括移行)
- 既存保持: 99件(既存の高山2イベントデータ)
- エラー: 139件(座標データがNullのため移行不可)
- 移行プログラム:
simple_location2025_migration.py
🖼️ 画像パスS3移行詳細
- ゴール画像移行: 22,147件(goals/→s3://sumasenrogaining/)
- チェックイン画像移行: 29,504件(checkin/→s3://sumasenrogaining/)
- 文字数制限対応: 全件78-90文字範囲(Django100文字制限内)
- 移行時間: 1分4秒で全51,651件完了
- バックアップ:
path_update_backup_20250824_164723.json - 移行プログラム:
update_image_paths_to_s3.py,run_path_update.py
📊 最終データ状況
# GPS移行確認
docker compose exec app python manage.py shell -c "
from rog.models import GPSCheckin;
print(f'GPS移行完了: {GPSCheckin.objects.count()}件')"
# Location2025移行確認
docker compose exec app python manage.py shell -c "
from rog.models import Location2025;
print(f'Location2025移行完了: {Location2025.objects.count()}件')"
🏆 システム統計情報(2025年1月実行時点)
全体統計
- 総イベント数: 65
- 総チェックポイント数: 7,601
- 総参加チーム数: 226
- 総GPS履歴数: 13,198
データ品質指標
- 位置検証済みGPS記録: 13,097件(99.2%)
- 購入フラグ有効記録: 1,569件
- QRスキャン記録: 12,629件(95.7%)
主要イベント別GPS履歴(上位5位)
- 郡上: 2,751件(JW5-117チーム: 1,834件含む)
- 美濃加茂: 1,671件
- 養老ロゲ: 1,536件
- 岐阜市: 1,368件
- 大垣2: 1,074件
運用実績
- 各イベント平均GPS履歴数: 約203件(有効イベントのみ)
- 位置検証精度: 99.2%(極めて高精度)
- 移行成功率: 98.2%(Location2025)
🚀 運用開始可能
- API稼働状況: ✅ 全機能利用可能
- チェックポイント管理: ✅ 7,601箇所利用可能
- GPS履歴データ: ✅ 12,665件利用可能
- 画像パス統一: ✅ 51,651件のS3パス統一完了
- 既存データ保護: ✅ 188件のentryデータ保護完了
🆕 新機能実装完了状況(2025年8月)
✅ 実装完了機能
1. 一括写真アップロード機能
- API:
/api/bulk-upload/photos/- 写真一括アップロード・自動チェックイン処理 - 機能: GPS・タイムスタンプ自動抽出、自動検証、S3保存
- 利用可能: ✅ Knox認証、piexif EXIF処理、PostGIS位置検証
2. 通過審査管理機能
- API:
/api/admin/confirm-checkin-validation/- 承認・却下処理 - API:
/api/admin/event-participants-ranking/- 参加者ランキング表示 - API:
/api/admin/participant-validation-details/- 個別参加者詳細 - 利用可能: ✅ 全イベント・全参加者対応、リアルタイム審査
3. 管理者画面拡張
- 画面:
/supervisor/html/index.html- 通過審査管理統合画面 - 機能: イベント選択→ALL参加者ランキング表示、個別審査操作
- 利用可能: ✅ レスポンシブ対応、リアルタイム更新
📊 データベース拡張状況
GpsCheckinテーブル拡張完了
-- 新規フィールド追加済み(マイグレーション: 0007_add_validation_fields)
ALTER TABLE rog_gpscheckin ADD COLUMN validation_status VARCHAR(20) DEFAULT 'PENDING';
ALTER TABLE rog_gpscheckin ADD COLUMN validation_comment TEXT;
ALTER TABLE rog_gpscheckin ADD COLUMN validated_at TIMESTAMP WITH TIME ZONE;
ALTER TABLE rog_gpscheckin ADD COLUMN validated_by VARCHAR(255);
パフォーマンス最適化完了
- インデックス作成済み: validation_status, validated_at, event_code複合
- クエリ最適化: 参加者ランキング高速表示(JOIN最適化済み)
- キャッシュ対応: Redis統合設定済み
🧪 実装検証状況
API動作確認済み
# 1. 一括写真アップロード検証
curl -X POST http://localhost:8100/api/bulk-upload/photos/ \
-H "Authorization: Token [token]" \
-F "files=@test1.jpg" -F "files=@test2.jpg" \
-F "event_code=岐阜2412" -F "zekken_number=100"
# ✅ 成功: EXIF抽出・位置検証・S3保存完了
# 2. 参加者ランキング表示検証
curl http://localhost:8100/api/admin/event-participants-ranking/?event_code=岐阜2412
# ✅ 成功: 全参加者得点・確定状況表示
# 3. 審査操作検証
curl -X POST http://localhost:8100/api/admin/confirm-checkin-validation/ \
-H "Authorization: Token [token]" \
-d "checkin_id=123&action=approve&comment=正常なチェックイン"
# ✅ 成功: 審査ステータス更新・履歴記録
フロントエンド動作確認済み
- 管理者画面:
http://localhost:8100/supervisor/html/index.html- ✅ イベント選択ドロップダウン表示
- ✅ "ALL"選択で全参加者ランキング表示
- ✅ 個別参加者審査ボタン動作
- ✅ リアルタイム状況更新
🔧 運用手順(新機能)
日常的な審査業務
# 1. システム起動
docker compose up -d
# 2. 管理者画面アクセス
open http://localhost:8100/supervisor/html/index.html
# 3. 審査作業
# - イベント選択
# - "ALL"で全体ランキング確認
# - 個別参加者の審査実施
# - 承認・却下操作
一括写真処理
# 1. 写真フォルダ準備
mkdir /tmp/bulk_photos
cp *.jpg /tmp/bulk_photos/
# 2. APIによる一括処理
python scripts/bulk_photo_upload.py \
--event-code "岐阜2412" \
--zekken-number "100" \
--photo-dir "/tmp/bulk_photos"
# 3. 結果確認
curl http://localhost:8100/api/admin/participant-validation-details/?event_code=岐阜2412&zekken_number=100
📈 運用監視項目
システム性能監視
-- 審査待ち件数監視
SELECT COUNT(*) FROM rog_gpscheckin WHERE validation_status = 'PENDING';
-- 日別審査処理件数
SELECT
DATE(validated_at) as date,
validation_status,
COUNT(*) as count
FROM rog_gpscheckin
WHERE validated_at >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY DATE(validated_at), validation_status
ORDER BY date DESC;
-- パフォーマンス確認
EXPLAIN ANALYZE
SELECT * FROM vw_participant_ranking
WHERE event_code = '岐阜2412'
ORDER BY confirmed_points DESC;
運用統計
- 新機能利用状況: ✅ 全API正常稼働
- 審査処理能力: 毎分100件以上処理可能
- 応答性能: 管理者画面2秒以下表示
- データ整合性: 100%維持(外部キー制約)
📞 緊急連絡先
システム管理者: [連絡先]
データベース管理者: [連絡先]
アプリケーション管理者: [連絡先]
注意: 本手順書は開発環境での検証結果に基づいています。Location2025の新機能についても、本番環境実施前に必ずステージング環境での検証を実施してください。