feat: add Django web app, CloudKit sync, dashboard, and game_datetime_utc export

Adds the full Django application layer on top of sportstime_parser:
- core: Sport, Team, Stadium, Game models with aliases and league structure
- scraper: orchestration engine, adapter, job management, Celery tasks
- cloudkit: CloudKit sync client, sync state tracking, sync jobs
- dashboard: staff dashboard for monitoring scrapers, sync, review queue
- notifications: email reports for scrape/sync results
- Docker setup for deployment (Dockerfile, docker-compose, entrypoint)

Game exports now use game_datetime_utc (ISO 8601 UTC) instead of
venue-local date+time strings, matching the canonical format used
by the iOS app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-02-19 14:04:27 -06:00
parent 4353d5943c
commit 63acf7accb
114 changed files with 13070 additions and 887 deletions

49
cloudkit/resources.py Normal file
View File

@@ -0,0 +1,49 @@
"""Import/Export resources for cloudkit models."""
from import_export import resources, fields
from import_export.widgets import ForeignKeyWidget
from .models import CloudKitConfiguration, CloudKitSyncState, CloudKitSyncJob
class CloudKitConfigurationResource(resources.ModelResource):
class Meta:
model = CloudKitConfiguration
import_id_fields = ['name']
fields = [
'name', 'environment', 'container_id', 'key_id',
'is_active', 'batch_size', 'auto_sync_after_scrape',
]
export_order = fields
# Exclude private_key for security
exclude = ['private_key', 'private_key_path']
class CloudKitSyncStateResource(resources.ModelResource):
class Meta:
model = CloudKitSyncState
import_id_fields = ['record_type', 'record_id']
fields = [
'record_type', 'record_id', 'cloudkit_record_name',
'sync_status', 'local_hash', 'remote_change_tag',
'last_synced', 'last_error', 'retry_count',
]
export_order = fields
class CloudKitSyncJobResource(resources.ModelResource):
configuration = fields.Field(
column_name='configuration',
attribute='configuration',
widget=ForeignKeyWidget(CloudKitConfiguration, 'name')
)
class Meta:
model = CloudKitSyncJob
fields = [
'id', 'configuration', 'status', 'triggered_by',
'started_at', 'finished_at',
'records_synced', 'records_created', 'records_updated',
'records_deleted', 'records_failed',
'error_message', 'created_at',
]
export_order = fields