#!/usr/bin/env python """ LocationからLocation2025への完全データ移行スクリプト(フィールド追加版) 更新内容: - photos, videos, remark, tags, evaluation_value, hidden_location フィールドを追加 - cp_pointとphoto_pointは同じもので、checkin_pointとして移行 - location.cpを直接location2025.cp_numberに書き込み """ import os import django # Django設定 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') django.setup() from rog.models import Location, Location2025, NewEvent2 from django.contrib.auth import get_user_model from django.contrib.gis.geos import Point from collections import defaultdict 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を取得し、cp_number+event_idのユニークな組み合わせのみを処理 print('\n3. ユニークなcp_number+event_idの組み合わせで移行中...') locations = Location.objects.all() processed_combinations = set() migrated_count = 0 skipped_count = 0 error_count = 0 event_stats = defaultdict(int) for location in locations: try: # 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 + event_idの組み合わせを確認 combination_key = (location.cp, matched_event.id) if combination_key in processed_combinations: skipped_count += 1 continue # この組み合わせを処理済みとしてマーク processed_combinations.add(combination_key) # 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レコードを作成(update_or_create使用) location2025, created = Location2025.objects.update_or_create( cp_number=location.cp, # location.cpを直接使用 event=matched_event, defaults={ 'cp_name': location.location_name or '', '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とphoto_pointは同じもので、checkin_pointとして移行 'cp_point': int(location.checkin_point) if location.checkin_point else 0, 'photo_point': int(location.checkin_point) if location.checkin_point else 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 '', # 追加フィールド 'photos': location.photos or '', 'videos': location.videos or '', 'remark': location.remark or '', 'tags': location.tags or '', 'evaluation_value': location.evaluation_value or '', 'hidden_location': location.hidden_location or False, # 管理情報 'is_active': True, 'sort_order': 0, 'csv_source_file': 'migration_from_location', 'created_by': default_user, 'updated_by': default_user, } ) if created: migrated_count += 1 event_stats[matched_event_code] += 1 if migrated_count % 100 == 0: print(f' 進捗: {migrated_count}件完了') except Exception as e: print(f' ❌ エラー: CP {location.cp} - {str(e)}') error_count += 1 # 4. 結果サマリー print(f'\n=== 移行結果サマリー ===') print(f'移行完了: {migrated_count}件') print(f'スキップ: {skipped_count}件') print(f'エラー: {error_count}件') print(f'総処理: {migrated_count + skipped_count + error_count}件') # 5. Location2025の最終件数確認 final_count = Location2025.objects.count() print(f'\nLocation2025最終件数: {final_count}件') # 6. event_code別の統計 print(f'\n=== event_code別統計 ===') for event_code, count in event_stats.items(): print(f' Event "{event_code}": {count}件') # 7. 移行されたフィールドの確認 if migrated_count > 0: print('\n=== 移行フィールド確認(サンプル) ===') sample = Location2025.objects.first() print(f' CP番号: {sample.cp_number}') print(f' CP名: {sample.cp_name}') print(f' CPポイント: {sample.cp_point}') print(f' フォトポイント: {sample.photo_point}') print(f' 写真: {sample.photos[:50]}...' if sample.photos else ' 写真: (空)') print(f' 動画: {sample.videos[:50]}...' if sample.videos else ' 動画: (空)') print(f' タグ: {sample.tags[:50]}...' if sample.tags else ' タグ: (空)') print(f' 評価値: {sample.evaluation_value}') print(f' 隠しロケーション: {sample.hidden_location}') print('\n✅ 全フィールド対応のデータ移行が正常に完了しました') if __name__ == "__main__": main()