#!/usr/bin/env python """ old_rogdb から rogdb への段階的FC岐阜データ移行スクリプト 1. Team/Member → 2. 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 print("=== old_rogdb から FC岐阜データ段階的移行 ===") try: # old_rogdbに直接接続 old_conn = psycopg2.connect( host='postgres-db', database='old_rogdb', user='admin', password='admin123456' ) print("✅ old_rogdbに接続成功") # FC岐阜イベントを確認 fc_event = NewEvent2.objects.filter(id=10).first() if not fc_event: print("❌ FC岐阜イベント(ID:10)が見つかりません") old_conn.close() sys.exit(1) print(f"✅ FC岐阜イベント: {fc_event.event_name}") with old_conn.cursor() as old_cursor: # === STEP 1: Team & Member データ取得 === print("\\n=== STEP 1: Team & Member データ取得 ===") # FC岐阜関連のチーム情報を取得 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 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 = 10 ORDER BY rt.id; """) team_data = old_cursor.fetchall() print(f"FC岐阜関連チーム: {len(team_data)}件") # チームメンバー情報を取得 old_cursor.execute(""" SELECT rm.team_id, rm.user_id, cu.email, cu.firstname, cu.lastname 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 = 10 ORDER BY rm.team_id, rm.user_id; """) member_data = old_cursor.fetchall() print(f"FC岐阜関連メンバー: {len(member_data)}件") # チーム別メンバー数を確認 team_member_count = {} for team_id, user_id, email, first_name, last_name in member_data: if team_id not in team_member_count: team_member_count[team_id] = 0 team_member_count[team_id] += 1 print("\\nチーム別メンバー数:") for team_id, count in team_member_count.items(): print(f" Team {team_id}: {count}名") # === STEP 2: ユーザー移行 === print("\\n=== STEP 2: ユーザー移行 ===") # 関連するすべてのユーザーを取得 all_user_ids = set() for _, _, owner_id, _, _, _, _, _ in team_data: if owner_id: all_user_ids.add(owner_id) for _, user_id, _, _, _ in member_data: all_user_ids.add(user_id) if all_user_ids: old_cursor.execute(f""" SELECT id, email, firstname, lastname, date_joined FROM rog_customuser WHERE id IN ({','.join(map(str, all_user_ids))}) """) user_data = old_cursor.fetchall() print(f"移行対象ユーザー: {len(user_data)}件") migrated_users = 0 for user_id, email, first_name, last_name, date_joined in 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 print(f" ユーザー作成: {email} ({first_name} {last_name})") print(f"✅ ユーザー移行完了: {migrated_users}件作成") # === STEP 3: カテゴリ移行 === print("\\n=== STEP 3: カテゴリ移行 ===") migrated_categories = 0 for _, _, _, cat_id, cat_name, _, _, _ in team_data: if cat_id and cat_name: 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: チーム移行 ===") migrated_teams = 0 for team_id, team_name, owner_id, cat_id, cat_name, email, first_name, last_name in team_data: 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': fc_event.id } ) if created: migrated_teams += 1 print(f" チーム作成: {team_name} (ID: {team_id})") except Exception as e: print(f" ❌ チーム作成エラー: {team_name} - {e}") print(f"✅ チーム移行完了: {migrated_teams}件作成") # === STEP 5: メンバー移行 === print("\\n=== STEP 5: メンバー移行 ===") migrated_members = 0 for team_id, user_id, email, first_name, last_name in member_data: 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: migrated_members += 1 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"✅ メンバー移行完了: {migrated_members}件作成") # === STEP 6: エントリー移行 === print("\\n=== STEP 6: エントリー移行 ===") # まず、現在のDBのis_trialフィールドにデフォルト値を設定 print("データベーステーブルのis_trialフィールドを修正中...") from django.db import connection as django_conn with django_conn.cursor() as django_cursor: try: # is_trialフィールドにデフォルト値を設定 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}") # FC岐阜エントリーデータを取得 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 = 10 ORDER BY re.zekken_number; """) entry_data = old_cursor.fetchall() migrated_entries = 0 for entry_id, team_id, zekken, label, team_name, cat_id, date, owner_id, cat_name in entry_data: try: # チームとカテゴリを取得 team = Team.objects.get(id=team_id) category = NewCategory.objects.get(id=cat_id) if cat_id else None # まず既存のエントリーをチェック existing_entry = Entry.objects.filter(team=team, event=fc_event).first() if existing_entry: print(f" 🔄 既存エントリー: {team_name} - ゼッケン{existing_entry.zekken_number}") continue # SQLで直接エントリーを挿入 from django.db import connection as django_conn 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); """, [ fc_event.start_datetime, # date cat_id, # category_id fc_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"FC岐阜-{zekken}", # zekken_label False, # is_trial False, # staff_privileges False, # can_access_private_events 'approved' # team_validation_status ]) migrated_entries += 1 print(f" ✅ エントリー作成: {team_name} - ゼッケン{zekken}") except Team.DoesNotExist: print(f" ❌ チーム{team_id}が見つかりません: {team_name}") except Exception as e: print(f" ❌ エントリー作成エラー: {team_name} - {e}") print(f"✅ エントリー移行完了: {migrated_entries}件作成") old_conn.close() # === 最終確認 === print("\\n=== 移行結果確認 ===") fc_entries = Entry.objects.filter(event=fc_event).order_by('zekken_number') print(f"FC岐阜イベント総エントリー: {fc_entries.count()}件") if fc_entries.exists(): print("\\n🎉 ゼッケン番号一覧(最初の10件):") for entry in fc_entries[:10]: print(f" ゼッケン{entry.zekken_number}: {entry.team.team_name}") print("\\n🎉 FC岐阜イベントのゼッケン番号表示問題が解決されました!") print("\\n🎯 通過審査管理画面でFC岐阜を選択すると、ゼッケン番号が表示されるようになります。") else: print("❌ エントリーデータの移行に失敗しました") except Exception as e: print(f"❌ エラーが発生しました: {e}") import traceback traceback.print_exc()