301 lines
14 KiB
Python
301 lines
14 KiB
Python
|
|
#!/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()
|