#!/usr/bin/env python """ LocationからLocation2025への完全データ移行スクリプト(最終版) """ from rog.models import Location, Location2025, NewEvent2 from django.contrib.auth import get_user_model from django.contrib.gis.geos import Point def main(): User = get_user_model() default_user = User.objects.first() print('=== Location から Location2025 への完全データ移行(最終版) ===') # 1. Location2025の既存データを削除 print('\n1. Location2025の既存データを削除中...') deleted_count = Location2025.objects.count() Location2025.objects.all().delete() print(f' 削除済み: {deleted_count}件') # 2. NewEvent2のevent_codeマップを作成 print('\n2. NewEvent2のevent_codeマップを作成中...') events = NewEvent2.objects.filter(event_code__isnull=False).exclude(event_code='') event_code_map = {} for event in events: event_code_map[event.event_code] = event print(f' 有効なevent_code数: {len(event_code_map)}件') # 3. 全Locationを取得 print('\n3. 移行対象のLocationレコードを取得中...') locations = Location.objects.all() print(f' 総Location数: {locations.count()}件') # 4. 条件に合致するLocationを移行 print('\n4. データ移行中...') migrated_count = 0 skipped_count = 0 error_count = 0 cp_number_counter = {} # event_id別のcp_numberカウンター for i, location in enumerate(locations): try: # 進捗表示(1000件ごと) if i % 1000 == 0: print(f' 処理中: {i}/{locations.count()}件') # groupが空の場合はスキップ if not location.group: skipped_count += 1 continue # location.groupに含まれるevent_codeを検索 matched_event = None matched_event_code = None for event_code, event in event_code_map.items(): if event_code in location.group: matched_event = event matched_event_code = event_code break # マッチするevent_codeがない場合はスキップ if not matched_event: skipped_count += 1 continue # cp_numberの処理(0の場合は自動採番) cp_number = int(location.cp) if location.cp else 0 if cp_number == 0: # event_id別に自動採番 if matched_event.id not in cp_number_counter: cp_number_counter[matched_event.id] = 10000 # 10000から開始 cp_number = cp_number_counter[matched_event.id] cp_number_counter[matched_event.id] += 1 # MultiPointからPointに変換 point_location = None if location.geom and len(location.geom) > 0: first_point = location.geom[0] point_location = Point(first_point.x, first_point.y) elif location.longitude and location.latitude: point_location = Point(location.longitude, location.latitude) # Location2025レコードを作成 location2025 = Location2025( cp_number=cp_number, event=matched_event, cp_name=location.location_name, sub_loc_id=location.sub_loc_id or '', subcategory=location.subcategory or '', latitude=location.latitude or 0.0, longitude=location.longitude or 0.0, location=point_location, cp_point=int(location.checkin_point) if location.checkin_point else 0, photo_point=0, buy_point=int(location.buy_point) if location.buy_point else 0, checkin_radius=location.checkin_radius or 100.0, auto_checkin=location.auto_checkin or False, shop_closed=location.shop_closed or False, shop_shutdown=location.shop_shutdown or False, opening_hours='', address=location.address or '', phone=location.phone or '', website='', description=location.remark or '', is_active=True, sort_order=0, csv_source_file='migration_from_location', created_by=default_user, updated_by=default_user, ) location2025.save() migrated_count += 1 # 最初の10件は詳細ログ if migrated_count <= 10: print(f' ✅ 移行完了: {location.cp} -> {location2025.cp_number} ({location.location_name}) [Event: {matched_event_code}]') except Exception as e: print(f' ❌ エラー: {location.cp} - {str(e)}') error_count += 1 # 5. 結果サマリー print(f'\n=== 移行結果サマリー ===') print(f'移行完了: {migrated_count}件') print(f'スキップ: {skipped_count}件') print(f'エラー: {error_count}件') print(f'総処理: {migrated_count + skipped_count + error_count}件') # 6. Location2025の最終件数確認 final_count = Location2025.objects.count() print(f'\nLocation2025最終件数: {final_count}件') # 7. event_id別の統計 print(f'\n=== event_id別統計 ===') for event_code, event in event_code_map.items(): count = Location2025.objects.filter(event=event).count() if count > 0: print(f' Event "{event_code}" (ID: {event.id}): {count}件') if migrated_count > 0: print('\n✅ データ移行が正常に完了しました') else: print('\n⚠️ 移行されたデータがありません') if __name__ == "__main__": main()