Fix migration error
This commit is contained in:
377
migrate_all_events_complete.py
Normal file
377
migrate_all_events_complete.py
Normal file
@ -0,0 +1,377 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
old_rogdb から rogdb への全イベントデータ移行スクリプト
|
||||
FC岐阜の成功事例をベースに全てのイベントのteam/member/entryを移行
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import django
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||
django.setup()
|
||||
|
||||
from django.db import transaction
|
||||
from rog.models import NewEvent2, Team, Entry, NewCategory, CustomUser, Member
|
||||
import psycopg2
|
||||
from collections import defaultdict
|
||||
|
||||
print("=== old_rogdb から 全イベントデータ移行 ===")
|
||||
|
||||
try:
|
||||
# old_rogdbに直接接続
|
||||
old_conn = psycopg2.connect(
|
||||
host='postgres-db',
|
||||
database='old_rogdb',
|
||||
user='admin',
|
||||
password='admin123456'
|
||||
)
|
||||
|
||||
print("✅ old_rogdbに接続成功")
|
||||
|
||||
with old_conn.cursor() as old_cursor:
|
||||
# === STEP 0: 移行対象イベントの確認 ===
|
||||
print("\\n=== STEP 0: 移行対象イベントの確認 ===")
|
||||
|
||||
# 新DBのイベント一覧を取得
|
||||
existing_events = list(NewEvent2.objects.values_list('id', 'event_name'))
|
||||
existing_event_ids = [event_id for event_id, _ in existing_events]
|
||||
|
||||
print(f"新DB既存イベント: {len(existing_events)}件")
|
||||
for event_id, event_name in existing_events[:10]:
|
||||
print(f" Event {event_id}: {event_name}")
|
||||
|
||||
# old_rogdbでエントリーがあるイベントを確認
|
||||
old_cursor.execute("""
|
||||
SELECT e.id, e.event_name, COUNT(re.id) as entry_count
|
||||
FROM rog_newevent2 e
|
||||
LEFT JOIN rog_entry re ON e.id = re.event_id
|
||||
WHERE e.id IN ({})
|
||||
GROUP BY e.id, e.event_name
|
||||
HAVING COUNT(re.id) > 0
|
||||
ORDER BY COUNT(re.id) DESC;
|
||||
""".format(','.join(map(str, existing_event_ids))))
|
||||
|
||||
events_with_entries = old_cursor.fetchall()
|
||||
print(f"\\n移行対象イベント(エントリーあり): {len(events_with_entries)}件")
|
||||
for event_id, event_name, entry_count in events_with_entries:
|
||||
print(f" Event {event_id}: '{event_name}' - {entry_count}件のエントリー")
|
||||
|
||||
# === STEP 1: 全イベントのTeam & Member データ取得 ===
|
||||
print("\\n=== STEP 1: 全イベントの Team & Member データ取得 ===")
|
||||
|
||||
# 全イベントのチーム情報を取得
|
||||
old_cursor.execute("""
|
||||
SELECT DISTINCT rt.id, rt.team_name, rt.owner_id, rt.category_id,
|
||||
rc.category_name, cu.email, cu.firstname, cu.lastname, re.event_id
|
||||
FROM rog_entry re
|
||||
JOIN rog_team rt ON re.team_id = rt.id
|
||||
LEFT JOIN rog_newcategory rc ON rt.category_id = rc.id
|
||||
LEFT JOIN rog_customuser cu ON rt.owner_id = cu.id
|
||||
WHERE re.event_id IN ({})
|
||||
ORDER BY re.event_id, rt.id;
|
||||
""".format(','.join(map(str, existing_event_ids))))
|
||||
|
||||
all_team_data = old_cursor.fetchall()
|
||||
print(f"全イベント関連チーム: {len(all_team_data)}件")
|
||||
|
||||
# イベント別チーム数統計
|
||||
teams_by_event = defaultdict(int)
|
||||
teams_by_event = defaultdict(int)
|
||||
for _, _, _, _, _, _, _, _, event_id in all_team_data:
|
||||
teams_by_event[event_id] += 1
|
||||
|
||||
print("\\nイベント別チーム数:")
|
||||
for event_id, count in sorted(teams_by_event.items()):
|
||||
event_name = next((name for eid, name in existing_events if eid == event_id), "不明")
|
||||
print(f" Event {event_id} ({event_name}): {count}チーム")
|
||||
|
||||
# 全イベントのメンバー情報を取得
|
||||
old_cursor.execute("""
|
||||
SELECT rm.team_id, rm.user_id, cu.email, cu.firstname, cu.lastname, re.event_id
|
||||
FROM rog_entry re
|
||||
JOIN rog_member rm ON re.team_id = rm.team_id
|
||||
JOIN rog_customuser cu ON rm.user_id = cu.id
|
||||
WHERE re.event_id IN ({})
|
||||
ORDER BY re.event_id, rm.team_id, rm.user_id;
|
||||
""".format(','.join(map(str, existing_event_ids))))
|
||||
|
||||
all_member_data = old_cursor.fetchall()
|
||||
print(f"全イベント関連メンバー: {len(all_member_data)}件")
|
||||
|
||||
# === STEP 2: ユーザー移行 ===
|
||||
print("\\n=== STEP 2: ユーザー移行 ===")
|
||||
|
||||
# 関連するすべてのユーザーを取得
|
||||
all_user_ids = set()
|
||||
for _, _, owner_id, _, _, _, _, _, _ in all_team_data:
|
||||
if owner_id:
|
||||
all_user_ids.add(owner_id)
|
||||
for _, user_id, _, _, _, _ in all_member_data:
|
||||
all_user_ids.add(user_id)
|
||||
|
||||
if all_user_ids:
|
||||
# 大量のユーザーIDに対応するため、バッチで処理
|
||||
user_batches = [list(all_user_ids)[i:i+100] for i in range(0, len(all_user_ids), 100)]
|
||||
all_user_data = []
|
||||
user_batches = [list(all_user_ids)[i:i+100] for i in range(0, len(all_user_ids), 100)]
|
||||
all_user_data = []
|
||||
|
||||
for batch in user_batches:
|
||||
old_cursor.execute(f"""
|
||||
SELECT id, email, firstname, lastname, date_joined
|
||||
FROM rog_customuser
|
||||
WHERE id IN ({','.join(map(str, batch))})
|
||||
""")
|
||||
all_user_data.extend(old_cursor.fetchall())
|
||||
|
||||
print(f"移行対象ユーザー: {len(all_user_data)}件")
|
||||
|
||||
migrated_users = 0
|
||||
for user_id, email, first_name, last_name, date_joined in all_user_data:
|
||||
user, created = CustomUser.objects.get_or_create(
|
||||
id=user_id,
|
||||
defaults={
|
||||
'email': email or f'user{user_id}@example.com',
|
||||
'first_name': first_name or '',
|
||||
'last_name': last_name or '',
|
||||
'username': email or f'user{user_id}',
|
||||
'date_joined': date_joined,
|
||||
'is_active': True
|
||||
}
|
||||
)
|
||||
if created:
|
||||
migrated_users += 1
|
||||
if migrated_users <= 10: # 最初の10件のみ表示
|
||||
print(f" ユーザー作成: {email} ({first_name} {last_name})")
|
||||
|
||||
print(f"✅ ユーザー移行完了: {migrated_users}件作成")
|
||||
|
||||
# === STEP 3: カテゴリ移行 ===
|
||||
print("\\n=== STEP 3: カテゴリ移行 ===")
|
||||
|
||||
migrated_categories = 0
|
||||
unique_categories = set()
|
||||
unique_categories = set()
|
||||
for _, _, _, cat_id, cat_name, _, _, _, _ in all_team_data:
|
||||
if cat_id and cat_name:
|
||||
unique_categories.add((cat_id, cat_name))
|
||||
|
||||
for cat_id, cat_name in unique_categories:
|
||||
category, created = NewCategory.objects.get_or_create(
|
||||
id=cat_id,
|
||||
defaults={
|
||||
'category_name': cat_name,
|
||||
'category_number': cat_id
|
||||
}
|
||||
)
|
||||
if created:
|
||||
migrated_categories += 1
|
||||
print(f" カテゴリ作成: {cat_name}")
|
||||
|
||||
print(f"✅ カテゴリ移行完了: {migrated_categories}件作成")
|
||||
|
||||
# === STEP 4: イベント別チーム移行 ===
|
||||
print("\\n=== STEP 4: イベント別チーム移行 ===")
|
||||
|
||||
total_migrated_teams = 0
|
||||
for event_id, event_name in existing_events:
|
||||
if event_id not in teams_by_event:
|
||||
continue
|
||||
|
||||
print(f"\\n--- Event {event_id}: {event_name} ---")
|
||||
event_teams = [data for data in all_team_data if data[8] == event_id]
|
||||
event_migrated_teams = 0
|
||||
|
||||
for team_id, team_name, owner_id, cat_id, cat_name, email, first_name, last_name, _ in event_teams:
|
||||
try:
|
||||
# カテゴリを取得
|
||||
category = NewCategory.objects.get(id=cat_id) if cat_id else None
|
||||
|
||||
# チームを作成
|
||||
team, created = Team.objects.get_or_create(
|
||||
id=team_id,
|
||||
defaults={
|
||||
'team_name': team_name,
|
||||
'owner_id': owner_id or 1,
|
||||
'category': category,
|
||||
'event_id': event_id
|
||||
}
|
||||
)
|
||||
|
||||
if created:
|
||||
event_migrated_teams += 1
|
||||
total_migrated_teams += 1
|
||||
if event_migrated_teams <= 3: # イベントごとに最初の3件のみ表示
|
||||
print(f" チーム作成: {team_name} (ID: {team_id})")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ チーム作成エラー: {team_name} - {e}")
|
||||
|
||||
print(f" ✅ {event_name}: {event_migrated_teams}件のチームを移行")
|
||||
|
||||
print(f"\\n✅ 全チーム移行完了: {total_migrated_teams}件作成")
|
||||
|
||||
# === STEP 5: メンバー移行 ===
|
||||
print("\\n=== STEP 5: メンバー移行 ===")
|
||||
|
||||
total_migrated_members = 0
|
||||
for event_id, event_name in existing_events:
|
||||
if event_id not in teams_by_event:
|
||||
continue
|
||||
|
||||
event_members = [data for data in all_member_data if data[5] == event_id]
|
||||
if not event_members:
|
||||
continue
|
||||
|
||||
print(f"\\n--- Event {event_id}: {event_name} ---")
|
||||
event_migrated_members = 0
|
||||
|
||||
for team_id, user_id, email, first_name, last_name, _ in event_members:
|
||||
try:
|
||||
# チームとユーザーを取得
|
||||
team = Team.objects.get(id=team_id)
|
||||
user = CustomUser.objects.get(id=user_id)
|
||||
|
||||
# メンバーを作成
|
||||
member, created = Member.objects.get_or_create(
|
||||
team=team,
|
||||
user=user
|
||||
)
|
||||
|
||||
if created:
|
||||
event_migrated_members += 1
|
||||
total_migrated_members += 1
|
||||
if event_migrated_members <= 3: # イベントごとに最初の3件のみ表示
|
||||
print(f" メンバー追加: {email} → {team.team_name}")
|
||||
|
||||
except Team.DoesNotExist:
|
||||
print(f" ⚠️ チーム{team_id}が見つかりません")
|
||||
except CustomUser.DoesNotExist:
|
||||
print(f" ⚠️ ユーザー{user_id}が見つかりません")
|
||||
except Exception as e:
|
||||
print(f" ❌ メンバー追加エラー: {e}")
|
||||
|
||||
print(f" ✅ {event_name}: {event_migrated_members}件のメンバーを移行")
|
||||
|
||||
print(f"\\n✅ 全メンバー移行完了: {total_migrated_members}件作成")
|
||||
|
||||
# === STEP 6: エントリー移行 ===
|
||||
print("\\n=== STEP 6: エントリー移行 ===")
|
||||
|
||||
# データベースのis_trialフィールドにデフォルト値を設定
|
||||
print("データベーステーブルのis_trialフィールドを修正中...")
|
||||
from django.db import connection as django_conn
|
||||
with django_conn.cursor() as django_cursor:
|
||||
try:
|
||||
django_cursor.execute("""
|
||||
ALTER TABLE rog_entry
|
||||
ALTER COLUMN is_trial SET DEFAULT FALSE;
|
||||
""")
|
||||
print(" ✅ is_trialフィールドにデフォルト値を設定")
|
||||
except Exception as e:
|
||||
print(f" ⚠️ is_trial修正エラー: {e}")
|
||||
|
||||
total_migrated_entries = 0
|
||||
for event_id, event_name in existing_events:
|
||||
if event_id not in teams_by_event:
|
||||
continue
|
||||
|
||||
print(f"\\n--- Event {event_id}: {event_name} ---")
|
||||
|
||||
# イベント別エントリーデータを取得
|
||||
old_cursor.execute("""
|
||||
SELECT re.id, re.team_id, re.zekken_number, re.zekken_label,
|
||||
rt.team_name, re.category_id, re.date, re.owner_id,
|
||||
rc.category_name
|
||||
FROM rog_entry re
|
||||
JOIN rog_team rt ON re.team_id = rt.id
|
||||
LEFT JOIN rog_newcategory rc ON re.category_id = rc.id
|
||||
WHERE re.event_id = %s
|
||||
ORDER BY re.zekken_number;
|
||||
""", [event_id])
|
||||
|
||||
event_entry_data = old_cursor.fetchall()
|
||||
event_migrated_entries = 0
|
||||
|
||||
for entry_id, team_id, zekken, label, team_name, cat_id, date, owner_id, cat_name in event_entry_data:
|
||||
try:
|
||||
# チームとカテゴリを取得
|
||||
team = Team.objects.get(id=team_id)
|
||||
category = NewCategory.objects.get(id=cat_id) if cat_id else None
|
||||
event_obj = NewEvent2.objects.get(id=event_id)
|
||||
|
||||
# 既存のエントリーをチェック
|
||||
existing_entry = Entry.objects.filter(team=team, event=event_obj).first()
|
||||
if existing_entry:
|
||||
continue
|
||||
|
||||
# SQLで直接エントリーを挿入
|
||||
with django_conn.cursor() as django_cursor:
|
||||
django_cursor.execute("""
|
||||
INSERT INTO rog_entry
|
||||
(date, category_id, event_id, owner_id, team_id, is_active,
|
||||
zekken_number, "hasGoaled", "hasParticipated", zekken_label,
|
||||
is_trial, staff_privileges, can_access_private_events, team_validation_status)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);
|
||||
""", [
|
||||
event_obj.start_datetime, # date
|
||||
cat_id, # category_id
|
||||
event_id, # event_id
|
||||
owner_id or 1, # owner_id
|
||||
team_id, # team_id
|
||||
True, # is_active
|
||||
int(zekken) if zekken else 0, # zekken_number
|
||||
False, # hasGoaled
|
||||
False, # hasParticipated
|
||||
label or f"{event_name}-{zekken}", # zekken_label
|
||||
False, # is_trial
|
||||
False, # staff_privileges
|
||||
False, # can_access_private_events
|
||||
'approved' # team_validation_status
|
||||
])
|
||||
|
||||
event_migrated_entries += 1
|
||||
total_migrated_entries += 1
|
||||
if event_migrated_entries <= 3: # イベントごとに最初の3件のみ表示
|
||||
print(f" エントリー作成: {team_name} - ゼッケン{zekken}")
|
||||
|
||||
except Team.DoesNotExist:
|
||||
print(f" ❌ チーム{team_id}が見つかりません: {team_name}")
|
||||
except NewEvent2.DoesNotExist:
|
||||
print(f" ❌ イベント{event_id}が見つかりません")
|
||||
except Exception as e:
|
||||
print(f" ❌ エントリー作成エラー: {team_name} - {e}")
|
||||
|
||||
print(f" ✅ {event_name}: {event_migrated_entries}件のエントリーを移行")
|
||||
|
||||
print(f"\\n✅ 全エントリー移行完了: {total_migrated_entries}件作成")
|
||||
|
||||
old_conn.close()
|
||||
|
||||
# === 最終確認 ===
|
||||
print("\\n=== 移行結果確認 ===")
|
||||
|
||||
total_teams = Team.objects.count()
|
||||
total_members = Member.objects.count()
|
||||
total_entries = Entry.objects.count()
|
||||
|
||||
print(f"総チーム数: {total_teams}件")
|
||||
print(f"総メンバー数: {total_members}件")
|
||||
print(f"総エントリー数: {total_entries}件")
|
||||
|
||||
# イベント別エントリー統計
|
||||
print("\\n=== イベント別エントリー統計 ===")
|
||||
for event_id, event_name in existing_events[:10]: # 最初の10件を表示
|
||||
entry_count = Entry.objects.filter(event_id=event_id).count()
|
||||
if entry_count > 0:
|
||||
print(f" {event_name}: {entry_count}件")
|
||||
|
||||
print("\\n🎉 全イベントデータ移行が完了しました!")
|
||||
print("🎯 通過審査管理画面で全てのイベントのゼッケン番号が表示されるようになります。")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ エラーが発生しました: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
Reference in New Issue
Block a user