Files
rogaining_srv/migrate_location_to_location2025_enhanced.py
2025-08-30 03:48:07 +09:00

177 lines
7.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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()