add Gpslog log
This commit is contained in:
@ -87,14 +87,14 @@ local all postgres peer
|
|||||||
# TYPE DATABASE USER ADDRESS METHOD
|
# TYPE DATABASE USER ADDRESS METHOD
|
||||||
|
|
||||||
# "local" is for Unix domain socket connections only
|
# "local" is for Unix domain socket connections only
|
||||||
local all all md5
|
local all all peer
|
||||||
# IPv4 local connections:
|
# IPv4 local connections:
|
||||||
host all all 127.0.0.1/32 md5
|
host all all 127.0.0.1/32 md5
|
||||||
# IPv6 local connections:
|
# IPv6 local connections:
|
||||||
host all all ::1/128 md5
|
host all all ::1/128 md5
|
||||||
# Allow replication connections from localhost, by a user with the
|
# Allow replication connections from localhost, by a user with the
|
||||||
# replication privilege.
|
# replication privilege.
|
||||||
local replication all md5
|
local replication all peer
|
||||||
host replication all 127.0.0.1/32 md5
|
host replication all 127.0.0.1/32 md5
|
||||||
host replication all ::1/128 md5
|
host replication all ::1/128 md5
|
||||||
host all all 172.0.0.0/8 md5
|
host all all 172.0.0.0/8 md5
|
||||||
|
|||||||
@ -621,11 +621,15 @@ def checkin_from_rogapp(request):
|
|||||||
logger.warning(f"[CHECKIN] Location2025 model issue - ID: {request_id}, CP: {cp_number}, Error: {e}")
|
logger.warning(f"[CHECKIN] Location2025 model issue - ID: {request_id}, CP: {cp_number}, Error: {e}")
|
||||||
|
|
||||||
# トランザクション開始
|
# トランザクション開始
|
||||||
|
logger.info(f"[GPSLOG] 🔄 Starting database transaction - ID: {request_id}")
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
logger.info(f"[GPSLOG] 🔒 Database transaction started successfully - ID: {request_id}")
|
||||||
|
|
||||||
# S3に画像をアップロードし、S3 URLを取得
|
# S3に画像をアップロードし、S3 URLを取得
|
||||||
s3_image_url = image_url
|
s3_image_url = image_url
|
||||||
if image_url and S3_AVAILABLE and s3_uploader:
|
if image_url and S3_AVAILABLE and s3_uploader:
|
||||||
try:
|
try:
|
||||||
|
logger.info(f"[GPSLOG] 📤 Starting S3 upload - ID: {request_id}, image_size: {len(image_url)} chars")
|
||||||
s3_image_url = s3_uploader.upload_checkin_image(
|
s3_image_url = s3_uploader.upload_checkin_image(
|
||||||
image_data=image_url,
|
image_data=image_url,
|
||||||
event_code=entry.event.event_name,
|
event_code=entry.event.event_name,
|
||||||
@ -633,32 +637,61 @@ def checkin_from_rogapp(request):
|
|||||||
cp_number=cp_number
|
cp_number=cp_number
|
||||||
)
|
)
|
||||||
logger.info(f"[CHECKIN] S3 upload - Original: {image_url[:50]}..., S3: {s3_image_url}")
|
logger.info(f"[CHECKIN] S3 upload - Original: {image_url[:50]}..., S3: {s3_image_url}")
|
||||||
|
logger.info(f"[GPSLOG] ✅ S3 upload completed - ID: {request_id}, new_url: {s3_image_url[:50]}...")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[CHECKIN] S3 upload failed, using original URL: {e}")
|
logger.error(f"[CHECKIN] S3 upload failed, using original URL: {e}")
|
||||||
|
logger.error(f"[GPSLOG] ❌ S3 upload failed - ID: {request_id}, error: {e}")
|
||||||
s3_image_url = image_url
|
s3_image_url = image_url
|
||||||
elif image_url:
|
elif image_url:
|
||||||
logger.info(f"[CHECKIN] S3 not available, using original URL")
|
logger.info(f"[CHECKIN] S3 not available, using original URL")
|
||||||
|
logger.info(f"[GPSLOG] ℹ️ S3 not available - ID: {request_id}, using original URL")
|
||||||
|
|
||||||
# serial_numberを自動生成(既存の最大値+1)
|
# serial_numberを自動生成(既存の最大値+1)
|
||||||
|
logger.info(f"[GPSLOG] 🔢 Calculating serial number for zekken: {entry.zekken_number}, event: {entry.event.event_name}")
|
||||||
max_serial = GpsLog.objects.filter(
|
max_serial = GpsLog.objects.filter(
|
||||||
zekken_number=entry.zekken_number,
|
zekken_number=entry.zekken_number,
|
||||||
event_code=entry.event.event_name
|
event_code=entry.event.event_name
|
||||||
).aggregate(max_serial=Max('serial_number'))['max_serial'] or 0
|
).aggregate(max_serial=Max('serial_number'))['max_serial'] or 0
|
||||||
|
|
||||||
|
new_serial = max_serial + 1
|
||||||
|
logger.info(f"[GPSLOG] 📊 Serial number calculation - max_existing: {max_serial}, new_serial: {new_serial}")
|
||||||
|
|
||||||
|
# GpsLogテーブルへの書き込み準備
|
||||||
|
gpslog_data = {
|
||||||
|
'serial_number': new_serial,
|
||||||
|
'zekken_number': entry.zekken_number,
|
||||||
|
'event_code': entry.event.event_name,
|
||||||
|
'cp_number': cp_number,
|
||||||
|
'image_address': s3_image_url, # S3 URLを保存
|
||||||
|
'checkin_time': timezone.now(),
|
||||||
|
'create_at': timezone.now(),
|
||||||
|
'update_at': timezone.now(),
|
||||||
|
'buy_flag': False,
|
||||||
|
'is_service_checked': False, # Location2025にはis_service_cpがないので、デフォルトでFalse
|
||||||
|
'colabo_company_memo': ""
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(f"[GPSLOG] 📝 Preparing GpsLog record - ID: {request_id}")
|
||||||
|
logger.info(f"[GPSLOG] 🏷️ Data: serial={new_serial}, zekken={entry.zekken_number}, event={entry.event.event_name}, cp={cp_number}")
|
||||||
|
logger.info(f"[GPSLOG] 🖼️ Image: has_image={bool(s3_image_url)}, url_length={len(s3_image_url) if s3_image_url else 0}")
|
||||||
|
logger.info(f"[GPSLOG] ⏰ Timestamps: checkin_time={gpslog_data['checkin_time']}")
|
||||||
|
|
||||||
# チェックポイント登録(S3 URLを使用)
|
# チェックポイント登録(S3 URLを使用)
|
||||||
checkpoint = GpsLog.objects.create(
|
try:
|
||||||
serial_number=max_serial + 1,
|
checkpoint = GpsLog.objects.create(**gpslog_data)
|
||||||
zekken_number=entry.zekken_number,
|
logger.info(f"[GPSLOG] ✅ GpsLog record created successfully - ID: {checkpoint.id}, request_id: {request_id}")
|
||||||
event_code=entry.event.event_name,
|
logger.info(f"[GPSLOG] 🎯 Created record details - DB_ID: {checkpoint.id}, serial: {checkpoint.serial_number}, checkin_time: {checkpoint.checkin_time}")
|
||||||
cp_number=cp_number,
|
|
||||||
image_address=s3_image_url, # S3 URLを保存
|
# 作成されたレコードの検証
|
||||||
checkin_time=timezone.now(),
|
if checkpoint.id:
|
||||||
create_at=timezone.now(),
|
logger.info(f"[GPSLOG] 🔍 Verification - Record exists in database with ID: {checkpoint.id}")
|
||||||
update_at=timezone.now(),
|
else:
|
||||||
buy_flag=False,
|
logger.warning(f"[GPSLOG] ⚠️ Warning - Record created but ID is None")
|
||||||
is_service_checked=False, # Location2025にはis_service_cpがないので、デフォルトでFalse
|
|
||||||
colabo_company_memo=""
|
except Exception as create_error:
|
||||||
)
|
logger.error(f"[GPSLOG] ❌ Failed to create GpsLog record - ID: {request_id}, Error: {create_error}")
|
||||||
|
logger.error(f"[GPSLOG] 📊 Failed data: {gpslog_data}")
|
||||||
|
raise create_error
|
||||||
|
|
||||||
# 獲得ポイントの計算(Location2025から取得)
|
# 獲得ポイントの計算(Location2025から取得)
|
||||||
point_value = event_cp.checkin_point if event_cp else 0
|
point_value = event_cp.checkin_point if event_cp else 0
|
||||||
@ -669,27 +702,34 @@ def checkin_from_rogapp(request):
|
|||||||
"total_points": point_value
|
"total_points": point_value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info(f"[GPSLOG] 🎯 Point calculation - base_points: {point_value}, bonus_points: {bonus_points}")
|
||||||
|
|
||||||
# カメラボーナス計算
|
# カメラボーナス計算
|
||||||
if image_url and event_cp and hasattr(event_cp, 'evaluation_value'):
|
if image_url and event_cp and hasattr(event_cp, 'evaluation_value'):
|
||||||
if event_cp.evaluation_value == "1": # 写真撮影必須ポイント
|
if event_cp.evaluation_value == "1": # 写真撮影必須ポイント
|
||||||
bonus_points += 5
|
bonus_points += 5
|
||||||
scoring_breakdown["camera_bonus"] = 5
|
scoring_breakdown["camera_bonus"] = 5
|
||||||
scoring_breakdown["total_points"] += 5
|
scoring_breakdown["total_points"] += 5
|
||||||
|
logger.info(f"[GPSLOG] 📸 Camera bonus applied - additional_points: 5, total: {scoring_breakdown['total_points']}")
|
||||||
|
|
||||||
logger.info(f"[CHECKIN] ✅ SUCCESS - Team: {team_name}, Zekken: {entry.zekken_number}, CP: {cp_number}, Points: {point_value}, Bonus: {bonus_points}, Time: {checkpoint.checkin_time}, Has Image: {bool(image_url)}, Buy Flag: {buy_flag}, Client IP: {client_ip}, User: {user_info}")
|
logger.info(f"[CHECKIN] ✅ SUCCESS - Team: {team_name}, Zekken: {entry.zekken_number}, CP: {cp_number}, Points: {point_value}, Bonus: {bonus_points}, Time: {checkpoint.checkin_time}, Has Image: {bool(image_url)}, Buy Flag: {buy_flag}, Client IP: {client_ip}, User: {user_info}")
|
||||||
|
logger.info(f"[GPSLOG] 🏆 FINAL RESULT - GpsLog_ID: {checkpoint.id}, Serial: {checkpoint.serial_number}, Total_Points: {scoring_breakdown['total_points']}, Request_ID: {request_id}")
|
||||||
|
|
||||||
# 競技状態を更新(スタート・ゴール以外のチェックイン時)
|
# 競技状態を更新(スタート・ゴール以外のチェックイン時)
|
||||||
if cp_number not in ["START", "GOAL", -2, -1]:
|
if cp_number not in ["START", "GOAL", -2, -1]:
|
||||||
entry.rogaining_counted = True
|
entry.rogaining_counted = True
|
||||||
entry.last_checkin_time = checkpoint.checkin_time
|
entry.last_checkin_time = checkpoint.checkin_time
|
||||||
entry.save()
|
entry.save()
|
||||||
logger.info(f"[CHECKIN] ✅ Competition status updated - rogaining_counted: True")
|
logger.info(f"[CHECKIN] ✅ Competition status updated - rogaining_counted: True, last_checkin_time: {checkpoint.checkin_time}")
|
||||||
|
logger.info(f"[GPSLOG] 🎮 Entry updated - entry_id: {entry.id}, rogaining_counted: {entry.rogaining_counted}")
|
||||||
|
else:
|
||||||
|
logger.info(f"[GPSLOG] ℹ️ Special checkpoint ({cp_number}) - Entry status not updated")
|
||||||
|
|
||||||
# 拡張情報があれば保存
|
# 拡張情報があれば保存
|
||||||
if gps_coordinates or camera_metadata:
|
if gps_coordinates or camera_metadata:
|
||||||
try:
|
try:
|
||||||
from ..models import CheckinExtended
|
from ..models import CheckinExtended
|
||||||
CheckinExtended.objects.create(
|
extended_record = CheckinExtended.objects.create(
|
||||||
gpslog=checkpoint,
|
gpslog=checkpoint,
|
||||||
gps_latitude=gps_coordinates.get('latitude'),
|
gps_latitude=gps_coordinates.get('latitude'),
|
||||||
gps_longitude=gps_coordinates.get('longitude'),
|
gps_longitude=gps_coordinates.get('longitude'),
|
||||||
@ -700,10 +740,14 @@ def checkin_from_rogapp(request):
|
|||||||
bonus_points=bonus_points,
|
bonus_points=bonus_points,
|
||||||
scoring_breakdown=scoring_breakdown
|
scoring_breakdown=scoring_breakdown
|
||||||
)
|
)
|
||||||
|
logger.info(f"[GPSLOG] 📋 Extended info saved - CheckinExtended_ID: {extended_record.id}")
|
||||||
except Exception as ext_error:
|
except Exception as ext_error:
|
||||||
logger.warning(f"Failed to save extended checkin info: {ext_error}")
|
logger.warning(f"[GPSLOG] ⚠️ Failed to save extended checkin info: {ext_error}")
|
||||||
|
else:
|
||||||
|
logger.info(f"[GPSLOG] ℹ️ No extended GPS/camera data to save")
|
||||||
|
|
||||||
return Response({
|
# レスポンス作成
|
||||||
|
response_data = {
|
||||||
"status": "OK",
|
"status": "OK",
|
||||||
"message": "チェックポイントが正常に登録されました",
|
"message": "チェックポイントが正常に登録されました",
|
||||||
"team_name": team_name,
|
"team_name": team_name,
|
||||||
@ -722,7 +766,13 @@ def checkin_from_rogapp(request):
|
|||||||
"ready_for_goal": entry.ready_for_goal,
|
"ready_for_goal": entry.ready_for_goal,
|
||||||
"is_at_goal": entry.is_at_goal
|
"is_at_goal": entry.is_at_goal
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
logger.info(f"[GPSLOG] 📤 Creating response - ID: {request_id}")
|
||||||
|
logger.info(f"[GPSLOG] 📊 Response summary - checkpoint_id: {checkpoint.id}, total_points: {scoring_breakdown['total_points']}, status: OK")
|
||||||
|
logger.info(f"[GPSLOG] 🔄 Transaction completed successfully - ID: {request_id}")
|
||||||
|
|
||||||
|
return Response(response_data)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# より詳細なエラー情報をログに記録
|
# より詳細なエラー情報をログに記録
|
||||||
@ -737,6 +787,13 @@ def checkin_from_rogapp(request):
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.error(f"[CHECKIN] ❌ DETAILED ERROR: {error_details}")
|
logger.error(f"[CHECKIN] ❌ DETAILED ERROR: {error_details}")
|
||||||
|
logger.error(f"[GPSLOG] ❌ GpsLog creation failed - ID: {request_id if 'request_id' in locals() else 'Unknown'}, Error: {type(e).__name__}: {str(e)}")
|
||||||
|
|
||||||
|
# GpsLogトランザクション失敗の詳細
|
||||||
|
if 'checkpoint' in locals():
|
||||||
|
logger.error(f"[GPSLOG] 💾 Transaction state - checkpoint created: True, checkpoint_id: {getattr(checkpoint, 'id', 'Unknown')}")
|
||||||
|
else:
|
||||||
|
logger.error(f"[GPSLOG] 💾 Transaction state - checkpoint created: False, transaction rolled back")
|
||||||
|
|
||||||
# より具体的なエラーメッセージを返す
|
# より具体的なエラーメッセージを返す
|
||||||
if "データベース" in str(e).lower() or "database" in str(e).lower():
|
if "データベース" in str(e).lower() or "database" in str(e).lower():
|
||||||
|
|||||||
@ -15,7 +15,7 @@ def run_db_query(query):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
cmd = [
|
cmd = [
|
||||||
'docker-compose', 'exec', '-T', 'db',
|
'docker-compose', 'exec', '-T', 'postgres-db',
|
||||||
'psql', '-U', 'admin', '-d', 'rogdb',
|
'psql', '-U', 'admin', '-d', 'rogdb',
|
||||||
'-c', query
|
'-c', query
|
||||||
]
|
]
|
||||||
@ -23,8 +23,7 @@ def run_db_query(query):
|
|||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
cmd,
|
cmd,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True
|
||||||
cwd='/Volumes/PortableSSD1TB/main/GifuTabi/rogaining_srv_exdb-2/rogaining_srv'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
|
|||||||
169
show_django_data.py
Normal file
169
show_django_data.py
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
Django管理コマンド: 最近のGpsLogとCheckinImagesデータを表示
|
||||||
|
docker-compose exec app python manage.py shell で実行
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import django
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
# Django設定
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
from django.utils import timezone
|
||||||
|
from rog.models import GpsLog, CheckinImages, CustomUser
|
||||||
|
from django.db import connection
|
||||||
|
|
||||||
|
def show_recent_data(days=7):
|
||||||
|
"""
|
||||||
|
最近のチェックインデータを表示
|
||||||
|
|
||||||
|
Args:
|
||||||
|
days (int): 過去何日分のデータを表示するか
|
||||||
|
"""
|
||||||
|
# 基準日時を計算
|
||||||
|
since_date = timezone.now() - timedelta(days=days)
|
||||||
|
|
||||||
|
print(f"=== 過去{days}日間のチェックインデータ ===")
|
||||||
|
print(f"検索期間: {since_date.strftime('%Y-%m-%d %H:%M:%S')} 以降")
|
||||||
|
print("-" * 80)
|
||||||
|
|
||||||
|
# GpsLogの最近のデータ
|
||||||
|
print("\n📍 GpsLog (チェックイン記録)")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
recent_gpslogs = GpsLog.objects.filter(
|
||||||
|
checkin_time__gte=since_date
|
||||||
|
).order_by('-checkin_time')[:20]
|
||||||
|
|
||||||
|
if recent_gpslogs:
|
||||||
|
print(f"件数: {len(recent_gpslogs)}件")
|
||||||
|
print()
|
||||||
|
print("ID | 時刻 | ゼッケン | イベント | CP | 画像URL")
|
||||||
|
print("-" * 80)
|
||||||
|
|
||||||
|
for log in recent_gpslogs:
|
||||||
|
image_status = "✅" if log.image_address else "❌"
|
||||||
|
image_url_preview = log.image_address[:40] + "..." if log.image_address and len(log.image_address) > 40 else log.image_address or ""
|
||||||
|
|
||||||
|
print(f"{log.id:5d} | {log.checkin_time.strftime('%m-%d %H:%M:%S'):15s} | {log.zekken_number:8s} | {log.event_code:11s} | {log.cp_number:4s} | {image_status} {image_url_preview}")
|
||||||
|
else:
|
||||||
|
print("データなし")
|
||||||
|
|
||||||
|
# CheckinImagesの最近のデータ
|
||||||
|
print(f"\n🖼️ CheckinImages (写真記録)")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
recent_images = CheckinImages.objects.filter(
|
||||||
|
checkintime__gte=since_date
|
||||||
|
).order_by('-checkintime')[:20]
|
||||||
|
|
||||||
|
if recent_images:
|
||||||
|
print(f"件数: {len(recent_images)}件")
|
||||||
|
print()
|
||||||
|
print("ID | 時刻 | ユーザー | チーム名 | イベント | CP | 画像ファイル")
|
||||||
|
print("-" * 100)
|
||||||
|
|
||||||
|
for img in recent_images:
|
||||||
|
user_name = img.user.email[:12] if img.user else "Unknown"
|
||||||
|
team_name = img.team_name[:12] if img.team_name else ""
|
||||||
|
event_code = img.event_code[:11] if img.event_code else ""
|
||||||
|
image_file = str(img.checkinimage)[:30] + "..." if len(str(img.checkinimage)) > 30 else str(img.checkinimage)
|
||||||
|
|
||||||
|
print(f"{img.id:5d} | {img.checkintime.strftime('%m-%d %H:%M:%S'):15s} | {user_name:12s} | {team_name:12s} | {event_code:11s} | {img.cp_number:4d} | {image_file}")
|
||||||
|
else:
|
||||||
|
print("データなし")
|
||||||
|
|
||||||
|
def show_summary_stats():
|
||||||
|
"""
|
||||||
|
チェックインデータの統計情報を表示
|
||||||
|
"""
|
||||||
|
print(f"\n📊 データベース統計")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
# 各テーブルの総件数
|
||||||
|
gpslog_total = GpsLog.objects.count()
|
||||||
|
checkinimages_total = CheckinImages.objects.count()
|
||||||
|
|
||||||
|
print(f"GpsLog 総件数: {gpslog_total:,}")
|
||||||
|
print(f"CheckinImages 総件数: {checkinimages_total:,}")
|
||||||
|
|
||||||
|
# 最新・最古のデータ
|
||||||
|
if gpslog_total > 0:
|
||||||
|
latest_gpslog = GpsLog.objects.order_by('-checkin_time').first()
|
||||||
|
oldest_gpslog = GpsLog.objects.order_by('checkin_time').first()
|
||||||
|
print(f"GpsLog 最新: {latest_gpslog.checkin_time.strftime('%Y-%m-%d %H:%M:%S') if latest_gpslog else 'N/A'}")
|
||||||
|
print(f"GpsLog 最古: {oldest_gpslog.checkin_time.strftime('%Y-%m-%d %H:%M:%S') if oldest_gpslog else 'N/A'}")
|
||||||
|
|
||||||
|
if checkinimages_total > 0:
|
||||||
|
latest_image = CheckinImages.objects.order_by('-checkintime').first()
|
||||||
|
oldest_image = CheckinImages.objects.order_by('checkintime').first()
|
||||||
|
print(f"CheckinImages 最新: {latest_image.checkintime.strftime('%Y-%m-%d %H:%M:%S') if latest_image else 'N/A'}")
|
||||||
|
print(f"CheckinImages 最古: {oldest_image.checkintime.strftime('%Y-%m-%d %H:%M:%S') if oldest_image else 'N/A'}")
|
||||||
|
|
||||||
|
# 画像有りのGpsLog件数
|
||||||
|
gpslog_with_images = GpsLog.objects.exclude(image_address__isnull=True).exclude(image_address='').count()
|
||||||
|
print(f"画像付きGpsLog: {gpslog_with_images:,} / {gpslog_total:,} ({gpslog_with_images/gpslog_total*100:.1f}%)" if gpslog_total > 0 else "画像付きGpsLog: 0")
|
||||||
|
|
||||||
|
def show_event_breakdown():
|
||||||
|
"""
|
||||||
|
イベント別のチェックイン件数を表示
|
||||||
|
"""
|
||||||
|
print(f"\n🎯 イベント別チェックイン件数")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
# GpsLogのイベント別集計
|
||||||
|
print("GpsLog:")
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT event_code, COUNT(*) as count
|
||||||
|
FROM rog_gpslog
|
||||||
|
GROUP BY event_code
|
||||||
|
ORDER BY count DESC
|
||||||
|
LIMIT 10
|
||||||
|
""")
|
||||||
|
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
print(f" {row[0]:15s}: {row[1]:,}件")
|
||||||
|
|
||||||
|
# CheckinImagesのイベント別集計
|
||||||
|
print("\nCheckinImages:")
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT event_code, COUNT(*) as count
|
||||||
|
FROM rog_checkinimages
|
||||||
|
GROUP BY event_code
|
||||||
|
ORDER BY count DESC
|
||||||
|
LIMIT 10
|
||||||
|
""")
|
||||||
|
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
print(f" {row[0]:15s}: {row[1]:,}件")
|
||||||
|
|
||||||
|
# 引数処理
|
||||||
|
days = 7
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
try:
|
||||||
|
days = int(sys.argv[1])
|
||||||
|
except ValueError:
|
||||||
|
print("⚠️ 日数は数値で指定してください")
|
||||||
|
days = 7
|
||||||
|
|
||||||
|
print("🏃♂️ ロゲイニング チェックインデータ表示ツール")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# データ表示
|
||||||
|
show_recent_data(days)
|
||||||
|
show_summary_stats()
|
||||||
|
show_event_breakdown()
|
||||||
|
|
||||||
|
print(f"\n✅ 完了")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ エラーが発生しました: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
Reference in New Issue
Block a user