feat(ad_control): new AdSurface + AdPlacement module for placement-based featured/top events
- New ad_control Django app: AdSurface + AdPlacement models with GLOBAL/LOCAL scope - Admin CRUD API at /api/v1/ad-control/ (JWT-protected): surfaces, placements, picker events - Placement lifecycle: DRAFT → ACTIVE|SCHEDULED → EXPIRED|DISABLED - LOCAL scope: Haversine ≤ 50km from event lat/lng (fixed radius, no config needed) - Consumer APIs: /api/events/featured-events/ and /api/events/top-events/ rewritten to use placement-based queries (same URL paths + response shape — no breaking changes) - Seed command: seed_surfaces --migrate converts existing is_featured/is_top_event booleans - mount: admin_api/urls.py → ad-control/, mobile_api/urls.py → replaced consumer views - settings.py: added ad_control to INSTALLED_APPS
This commit is contained in:
24
ad_control/admin.py
Normal file
24
ad_control/admin.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from django.contrib import admin
|
||||
from .models import AdSurface, AdPlacement
|
||||
|
||||
|
||||
@admin.register(AdSurface)
|
||||
class AdSurfaceAdmin(admin.ModelAdmin):
|
||||
list_display = ('key', 'name', 'max_slots', 'layout_type', 'sort_behavior', 'is_active', 'active_count')
|
||||
list_filter = ('is_active', 'layout_type')
|
||||
search_fields = ('key', 'name')
|
||||
readonly_fields = ('created_at',)
|
||||
|
||||
|
||||
@admin.register(AdPlacement)
|
||||
class AdPlacementAdmin(admin.ModelAdmin):
|
||||
list_display = (
|
||||
'id', 'event', 'surface', 'status', 'scope', 'priority',
|
||||
'rank', 'boost_label', 'start_at', 'end_at', 'created_at',
|
||||
)
|
||||
list_filter = ('status', 'scope', 'priority', 'surface')
|
||||
list_editable = ('status', 'scope', 'rank')
|
||||
search_fields = ('event__name', 'event__title', 'boost_label')
|
||||
raw_id_fields = ('event', 'created_by', 'updated_by')
|
||||
readonly_fields = ('created_at', 'updated_at')
|
||||
ordering = ('surface', 'rank')
|
||||
Reference in New Issue
Block a user