2026-04-06 12:10:06 +05:30
|
|
|
from django.urls import path, include
|
2026-03-24 14:46:03 +00:00
|
|
|
from rest_framework_simplejwt.views import TokenRefreshView
|
|
|
|
|
from . import views
|
|
|
|
|
|
|
|
|
|
urlpatterns = [
|
|
|
|
|
path('admin/auth/login/', views.AdminLoginView.as_view(), name='admin_login'),
|
|
|
|
|
path('auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
|
|
|
|
|
path('auth/me/', views.MeView.as_view(), name='auth_me'),
|
|
|
|
|
path('health/', views.HealthView.as_view(), name='health'),
|
feat: Phase 1+2 - JWT auth, dashboard metrics API, DB indexes
Phase 1 - JWT Auth Foundation:
- Replace token auth with djangorestframework-simplejwt
- POST /api/v1/admin/auth/login/ - returns access + refresh JWT
- POST /api/v1/auth/refresh/ - JWT refresh
- GET /api/v1/auth/me/ - current admin profile
- GET /api/v1/health/ - DB health check
- Add ledger app to INSTALLED_APPS
Phase 2 - Dashboard Metrics API:
- GET /api/v1/dashboard/metrics/ - revenue, partners, events, tickets
- GET /api/v1/dashboard/revenue/ - 7-day revenue vs payouts chart data
- GET /api/v1/dashboard/activity/ - last 10 platform events feed
- GET /api/v1/dashboard/actions/ - KYC queue, flagged events, pending payouts
DB Indexes (dashboard query optimisation):
- RazorpayTransaction: status, captured_at
- Partner: status, kyc_compliance_status
- Event: event_status, start_date, created_date
- Booking: created_date
- PaymentTransaction: payment_type, payment_transaction_status, payment_transaction_date
Infra:
- Add Dockerfile for eventify-backend container
- Add simplejwt to requirements.txt
- All 4 dashboard views use IsAuthenticated permission class
2026-03-24 17:46:41 +00:00
|
|
|
# Phase 2: Dashboard endpoints
|
|
|
|
|
path('dashboard/metrics/', views.DashboardMetricsView.as_view(), name='dashboard-metrics'),
|
|
|
|
|
path('dashboard/revenue/', views.DashboardRevenueView.as_view(), name='dashboard-revenue'),
|
|
|
|
|
path('dashboard/activity/', views.DashboardActivityView.as_view(), name='dashboard-activity'),
|
|
|
|
|
path('dashboard/actions/', views.DashboardActionsView.as_view(), name='dashboard-actions'),
|
feat: Phase 3 - Partners API (5 endpoints + 2 helpers)
- GET /api/v1/partners/stats/ - total, active, pendingKyc, highRisk counts
- GET /api/v1/partners/ - paginated list with status/kyc/type/search filters
- GET /api/v1/partners/:id/ - full detail with events, kycDocuments, dealTerms, ledger
- PATCH /api/v1/partners/:id/status/ - suspend/activate partner
- POST /api/v1/partners/:id/kyc/review/ - approve/reject KYC with reason
Helpers: _serialize_partner(), _partner_kyc_docs()
Status/KYC/type mapping: backend snake_case to frontend capitalised values
Risk score derived from kyc_compliance_status (high_risk=80, approved=5, etc.)
All views IsAuthenticated, models imported inside methods
2026-03-24 18:11:33 +00:00
|
|
|
# Phase 3: Partner endpoints
|
|
|
|
|
path('partners/stats/', views.PartnerStatsView.as_view(), name='partner-stats'),
|
|
|
|
|
path('partners/', views.PartnerListView.as_view(), name='partner-list'),
|
|
|
|
|
path('partners/<int:pk>/', views.PartnerDetailView.as_view(), name='partner-detail'),
|
|
|
|
|
path('partners/<int:pk>/status/', views.PartnerStatusView.as_view(), name='partner-status'),
|
|
|
|
|
path('partners/<int:pk>/kyc/review/', views.PartnerKYCReviewView.as_view(), name='partner-kyc-review'),
|
2026-04-21 22:55:08 +05:30
|
|
|
path('partners/<int:pk>/impersonate/', views.PartnerImpersonateView.as_view(), name='partner-impersonate'),
|
2026-04-02 04:06:02 +00:00
|
|
|
path('partners/onboard/', views.PartnerOnboardView.as_view(), name='partner-onboard'),
|
|
|
|
|
path('partners/<int:partner_id>/staff/', views.PartnerStaffCreateView.as_view(), name='partner-staff-create'),
|
feat(partner-portal): Sprint 1 — partner-me settings endpoints
Add 4 self-service endpoints under /api/v1/partners/me/:
- GET/PUT /partners/me/profile/ → name, email, phone, website, bio
- GET/PUT /partners/me/notifications/ → 4 boolean notification prefs
- GET/PUT /partners/me/payout/ → bank account + payout schedule
- POST /partners/me/change-password/ → current+new password change
Model changes (partner/models.py + migration 0002):
- Partner.bio TextField
- Partner.payout_* fields (holder name, account number, IFSC, bank name, schedule)
- Partner.notif_* boolean fields (new_booking, event_status, payout_update, weekly_report)
Auth: simplejwt Bearer token (same as all admin_api views).
Role guard: _require_partner() enforces partner/partner_manager/partner_staff
and verifies user.partner FK is non-null.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 11:02:34 +05:30
|
|
|
# Partner-Me: partner portal self-service (Sprint 1)
|
|
|
|
|
path('partners/me/profile/', views.PartnerMeProfileView.as_view(), name='partner-me-profile'),
|
|
|
|
|
path('partners/me/notifications/', views.PartnerMeNotificationsView.as_view(), name='partner-me-notifications'),
|
|
|
|
|
path('partners/me/payout/', views.PartnerMePayoutView.as_view(), name='partner-me-payout'),
|
|
|
|
|
path('partners/me/change-password/', views.PartnerMeChangePasswordView.as_view(), name='partner-me-change-password'),
|
2026-04-22 11:20:37 +05:30
|
|
|
# Partner-Me: events (Sprint 2)
|
|
|
|
|
path('partners/me/events/', views.PartnerMeEventsView.as_view(), name='partner-me-events'),
|
|
|
|
|
path('partners/me/events/<int:pk>/', views.PartnerMeEventDetailView.as_view(), name='partner-me-event-detail'),
|
|
|
|
|
path('partners/me/events/<int:pk>/duplicate/', views.PartnerMeEventDuplicateView.as_view(), name='partner-me-event-duplicate'),
|
2026-03-24 18:26:55 +00:00
|
|
|
path('users/metrics/', views.UserMetricsView.as_view(), name='user-metrics'),
|
|
|
|
|
path('users/', views.UserListView.as_view(), name='user-list'),
|
|
|
|
|
path('users/<int:pk>/', views.UserDetailView.as_view(), name='user-detail'),
|
|
|
|
|
path('users/<int:pk>/status/', views.UserStatusView.as_view(), name='user-status'),
|
2026-03-24 18:42:15 +00:00
|
|
|
# Phase 5: Events endpoints
|
|
|
|
|
path('events/stats/', views.EventStatsView.as_view(), name='event-stats'),
|
|
|
|
|
path('events/', views.EventListView.as_view(), name='event-list'),
|
|
|
|
|
path('events/<int:pk>/', views.EventDetailView.as_view(), name='event-detail'),
|
2026-03-25 12:23:21 +00:00
|
|
|
path('events/<int:pk>/update/', views.EventUpdateView.as_view(), name='event-update'),
|
2026-03-24 18:42:15 +00:00
|
|
|
path('events/<int:pk>/moderate/', views.EventModerationView.as_view(), name='event-moderate'),
|
2026-04-03 17:21:26 +05:30
|
|
|
path('events/<int:pk>/delete/', views.EventDeleteView.as_view(), name='event-delete'),
|
2026-03-25 12:23:21 +00:00
|
|
|
path('events/create/', views.EventCreateView.as_view(), name='event-create'),
|
|
|
|
|
path('events/types/', views.EventTypesView.as_view(), name='event-types'),
|
|
|
|
|
path('events/<int:pk>/primary-image/', views.EventPrimaryImageView.as_view(), name='event-primary-image'),
|
2026-03-24 19:05:33 +00:00
|
|
|
path('financials/metrics/', views.FinancialMetricsView.as_view(), name='financial-metrics'),
|
|
|
|
|
path('financials/transactions/', views.TransactionListView.as_view(), name='transaction-list'),
|
|
|
|
|
path('financials/settlements/', views.SettlementListView.as_view(), name='settlement-list'),
|
|
|
|
|
path('financials/settlements/<int:pk>/release/', views.SettlementReleaseView.as_view(), name='settlement-release'),
|
2026-03-25 02:46:50 +00:00
|
|
|
|
|
|
|
|
path('reviews/metrics/', views.ReviewMetricsView.as_view(), name='review-metrics'),
|
|
|
|
|
path('reviews/', views.ReviewListView.as_view(), name='review-list'),
|
|
|
|
|
path('reviews/<int:pk>/moderate/', views.ReviewModerationView.as_view(), name='review-moderate'),
|
|
|
|
|
path('reviews/<int:pk>/', views.ReviewDeleteView.as_view(), name='review-delete'),
|
2026-03-25 12:23:21 +00:00
|
|
|
|
2026-04-07 10:48:04 +05:30
|
|
|
# Lead Manager
|
|
|
|
|
path('leads/metrics/', views.LeadMetricsView.as_view(), name='lead-metrics'),
|
|
|
|
|
path('leads/', views.LeadListView.as_view(), name='lead-list'),
|
|
|
|
|
path('leads/<int:pk>/', views.LeadDetailView.as_view(), name='lead-detail'),
|
|
|
|
|
path('leads/<int:pk>/update/', views.LeadUpdateView.as_view(), name='lead-update'),
|
|
|
|
|
|
2026-04-02 04:06:02 +00:00
|
|
|
path('gamification/submit-event/', views.GamificationSubmitEventView.as_view(), name='gamification-submit-event'),
|
|
|
|
|
path('gamification/submit-event', views.GamificationSubmitEventView.as_view()),
|
|
|
|
|
path('shop/items/', views.ShopItemsView.as_view(), name='shop-items'),
|
|
|
|
|
path('shop/items', views.ShopItemsView.as_view()),
|
|
|
|
|
path('shop/redeem/', views.ShopRedeemView.as_view(), name='shop-redeem'),
|
|
|
|
|
path('shop/redeem', views.ShopRedeemView.as_view()),
|
|
|
|
|
|
|
|
|
|
path('gamification/dashboard/', views.GamificationDashboardView.as_view(), name='gamification-dashboard'),
|
|
|
|
|
path('gamification/dashboard', views.GamificationDashboardView.as_view()),
|
|
|
|
|
|
2026-03-25 12:23:21 +00:00
|
|
|
# Payment gateway settings
|
|
|
|
|
path('settings/payment-gateway/active/', views.ActivePaymentGatewayView.as_view(), name='active-payment-gateway'),
|
|
|
|
|
path('settings/payment-gateways/', views.PaymentGatewaySettingsView.as_view(), name='payment-gateways'),
|
|
|
|
|
path('settings/payment-gateways/<int:pk>/', views.PaymentGatewaySettingsView.as_view(), name='payment-gateway-detail'),
|
2026-04-02 04:06:02 +00:00
|
|
|
|
|
|
|
|
# RBAC
|
|
|
|
|
path('rbac/departments/', views.DepartmentListCreateView.as_view(), name='rbac-department-list'),
|
|
|
|
|
path('rbac/departments/<int:pk>/', views.DepartmentDetailView.as_view(), name='rbac-department-detail'),
|
|
|
|
|
path('rbac/squads/', views.SquadListCreateView.as_view(), name='rbac-squad-list'),
|
|
|
|
|
path('rbac/squads/<int:pk>/', views.SquadDetailView.as_view(), name='rbac-squad-detail'),
|
|
|
|
|
path('rbac/staff/', views.StaffListView.as_view(), name='rbac-staff-list'),
|
|
|
|
|
path('rbac/staff/invite/', views.StaffInviteView.as_view(), name='rbac-staff-invite'),
|
|
|
|
|
path('rbac/staff/<int:pk>/', views.StaffUpdateView.as_view(), name='rbac-staff-update'),
|
|
|
|
|
path('rbac/staff/<int:pk>/deactivate/', views.StaffDeactivateView.as_view(), name='rbac-staff-deactivate'),
|
|
|
|
|
path('rbac/staff/<int:pk>/move/', views.StaffMoveView.as_view(), name='rbac-staff-move'),
|
|
|
|
|
path('rbac/roles/', views.RoleListCreateView.as_view(), name='rbac-role-list'),
|
|
|
|
|
path('rbac/roles/<int:pk>/', views.RoleDetailView.as_view(), name='rbac-role-detail'),
|
|
|
|
|
path('rbac/scopes/', views.ScopeListView.as_view(), name='rbac-scope-list'),
|
|
|
|
|
path('rbac/org-tree/', views.OrgTreeView.as_view(), name='rbac-org-tree'),
|
|
|
|
|
path('rbac/audit-log/', views.AuditLogListView.as_view(), name='rbac-audit-log'),
|
feat(audit): add Audit Log module — coverage, metrics endpoint, indexes
- UserStatusView, EventModerationView, ReviewModerationView,
PartnerKYCReviewView: each state change now emits _audit_log()
inside the same transaction.atomic() block so the log stays
consistent with DB state on partial failure
- AuditLogMetricsView: GET /api/v1/rbac/audit-log/metrics/ returns
total/today/week/distinct_users/by_action_group; 60 s cache with
?nocache=1 bypass
- AuditLogListView: free-text search (Q over action/target/user),
page_size bounded to [1, 200]
- accounts.User.ALL_MODULES += 'audit-log';
StaffProfile.SCOPE_TO_MODULE['audit'] = 'audit-log'
- Migration 0005: composite indexes (action,-created_at) and
(target_type,target_id) on AuditLog
- admin_api/tests.py: 11 tests covering list shape, search,
page bounds, metrics shape+nocache, suspend/ban/reinstate
audit emission
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 12:39:38 +05:30
|
|
|
path('rbac/audit-log/metrics/', views.AuditLogMetricsView.as_view(), name='rbac-audit-log-metrics'),
|
2026-04-06 12:10:06 +05:30
|
|
|
|
2026-04-20 11:41:46 +05:30
|
|
|
# Notifications (admin-side recurring email jobs)
|
|
|
|
|
path('notifications/types/', views.NotificationTypesView.as_view(), name='notification-types'),
|
|
|
|
|
path('notifications/schedules/', views.NotificationScheduleListView.as_view(), name='notification-schedule-list'),
|
|
|
|
|
path('notifications/schedules/<int:pk>/', views.NotificationScheduleDetailView.as_view(), name='notification-schedule-detail'),
|
|
|
|
|
path('notifications/schedules/<int:pk>/recipients/', views.NotificationRecipientView.as_view(), name='notification-recipient-create'),
|
|
|
|
|
path('notifications/schedules/<int:pk>/recipients/<int:rid>/', views.NotificationRecipientDetailView.as_view(), name='notification-recipient-detail'),
|
|
|
|
|
path('notifications/schedules/<int:pk>/send-now/', views.NotificationScheduleSendNowView.as_view(), name='notification-schedule-send-now'),
|
2026-04-20 11:53:33 +05:30
|
|
|
path('notifications/schedules/<int:pk>/test-send/', views.NotificationScheduleTestSendView.as_view(), name='notification-schedule-test-send'),
|
2026-04-20 11:41:46 +05:30
|
|
|
|
2026-04-06 12:10:06 +05:30
|
|
|
# Ad Control
|
|
|
|
|
path('ad-control/', include('ad_control.urls')),
|
2026-03-25 02:46:50 +00:00
|
|
|
]
|