Files
igny8/DJANGO-ADMIN-IMPROVEMENT-PLAN.md
IGNY8 VPS (Salman) 60263b4682 phase 1 partial
2025-12-13 22:12:25 +00:00

1625 lines
46 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
# Django Admin Improvement Plan
**Version:** 1.0.0
**Created:** December 13, 2025
**Status:** Planning Phase
**Priority:** 🔴 High - 4-6 weeks implementation
**Dependencies:** After Plan Management Implementation
---
## Executive Summary
This document outlines a comprehensive improvement plan for the IGNY8 Django Admin interface to transform it from a basic management tool into a powerful operational command center. The plan addresses UI/UX deficiencies, operational inefficiencies, missing monitoring capabilities, and organizational improvements.
**Key Objectives:**
- Enhance UI styling and user experience
- Reorganize sidebar menu for logical grouping
- Remove unused/empty models
- Add bulk operations and data export
- Implement Celery task monitoring
- Create operational dashboards
- Improve search and filtering capabilities
---
## Current State Analysis
### ✅ Strengths
1. **Custom Admin Site** - Igny8AdminSite with logical grouping
2. **Multi-Tenancy Support** - AccountAdminMixin and SiteSectorAdminMixin
3. **Payment Approval Workflow** - Comprehensive payment approval system
4. **Custom Actions** - API key generation, payment approval/rejection
5. **Field Customization** - Custom fieldsets and readonly fields
### ⚠️ Issues Identified
#### 1. **UI/UX Problems**
- No custom styling - uses default Django admin theme
- Basic, dated appearance
- Poor mobile responsiveness
- No dashboard widgets or charts
- Limited visual feedback for actions
- No color coding for statuses
#### 2. **Sidebar Menu Organization**
- Some groups have unclear purpose
- "Payments" group separated from "Billing & Tenancy"
- Missing PlanLimitUsage model (needs to be added)
- Some empty groups appearing
- Inconsistent naming conventions
#### 3. **Unused/Empty Models**
- **site_building** models referenced but don't exist:
- BusinessType
- AudienceProfile
- BrandPersonality
- HeroImageryDirection
- Duplicate model registrations:
- Invoice registered in both `business/billing/admin.py` and `modules/billing/admin.py`
- Payment registered twice (with comment noting one shouldn't be used)
- CreditPackage registered twice
- CreditCostConfig registered twice
#### 4. **Missing Features**
- No CSV/Excel export functionality
- Limited bulk operations (only 3 actions total)
- No Celery task monitoring interface
- No admin dashboard with metrics
- No data quality indicators
- No audit trail beyond basic LogEntry
- No advanced filtering (date ranges, etc.)
#### 5. **Operational Gaps**
- No at-risk account alerts
- No low credit warnings
- No failed automation alerts
- No WordPress sync status dashboard
- No performance metrics tracking
---
## Phase 1: Critical Fixes & UI Foundation (Week 1-2)
### 1.1 Remove Unused Models from Admin Site
**Problem:** site_building models referenced but don't exist, causing confusion
**Action:**
- Remove from `backend/igny8_core/admin/site.py` custom_groups:
- BusinessType
- AudienceProfile
- BrandPersonality
- HeroImageryDirection
**Files to modify:**
- `/data/app/igny8/backend/igny8_core/admin/site.py`
### 1.2 Resolve Duplicate Model Registrations
**Problem:** Multiple models registered twice causing conflicts
**Action:**
- Keep only `modules/billing/admin.py` versions (they have full workflow)
- Remove or comment out duplicates in `business/billing/admin.py`:
- Invoice
- Payment
- CreditPackage
- CreditCostConfig
**Files to modify:**
- `/data/app/igny8/backend/igny8_core/business/billing/admin.py`
### 1.3 Reorganize Sidebar Menu Groups
**Current Groups:**
1. Billing & Tenancy
2. Sites & Users
3. Global Reference Data
4. Planner
5. Writer Module
6. Thinker Module
7. System Configuration
8. Payments (separate!)
9. Integrations & Sync
10. Publishing
11. Optimization
12. Django Internals
**Proposed Reorganization:**
```python
'💰 Billing & Accounts': {
'models': [
('igny8_core_auth', 'Plan'),
('billing', 'PlanLimitUsage'), # ADD THIS
('igny8_core_auth', 'Account'),
('igny8_core_auth', 'Subscription'),
('billing', 'Invoice'),
('billing', 'Payment'),
('billing', 'CreditTransaction'),
('billing', 'CreditUsageLog'),
('billing', 'CreditPackage'),
('billing', 'PaymentMethodConfig'),
('billing', 'AccountPaymentMethod'),
('billing', 'CreditCostConfig'),
],
},
'👥 Sites & Users': {
'models': [
('igny8_core_auth', 'Site'),
('igny8_core_auth', 'Sector'),
('igny8_core_auth', 'User'),
('igny8_core_auth', 'SiteUserAccess'),
('igny8_core_auth', 'PasswordResetToken'),
],
},
'📚 Content Management': {
'models': [
('writer', 'Content'),
('writer', 'Tasks'),
('writer', 'Images'),
('writer', 'ContentTaxonomy'),
('writer', 'ContentAttribute'),
('writer', 'ContentTaxonomyRelation'),
('writer', 'ContentClusterMap'),
],
},
'🎯 Planning & Strategy': {
'models': [
('planner', 'Clusters'),
('planner', 'Keywords'),
('planner', 'ContentIdeas'),
('system', 'Strategy'),
],
},
'🔗 Integrations & Publishing': {
'models': [
('integration', 'SiteIntegration'),
('integration', 'SyncEvent'),
('publishing', 'PublishingRecord'),
('publishing', 'DeploymentRecord'),
],
},
'🤖 AI & Automation': {
'models': [
('ai', 'AITaskLog'),
('system', 'AIPrompt'),
('automation', 'AutomationConfig'),
('automation', 'AutomationRun'),
('optimization', 'OptimizationTask'),
],
},
'🌍 Global Reference Data': {
'models': [
('igny8_core_auth', 'Industry'),
('igny8_core_auth', 'IndustrySector'),
('igny8_core_auth', 'SeedKeyword'),
],
},
'⚙️ System Configuration': {
'models': [
('system', 'IntegrationSettings'),
('system', 'AuthorProfile'),
('system', 'SystemSettings'),
('system', 'AccountSettings'),
('system', 'UserSettings'),
('system', 'ModuleSettings'),
('system', 'AISettings'),
('system', 'ModuleEnableSettings'),
('system', 'SystemLog'),
('system', 'SystemStatus'),
],
},
'🔧 Django System': {
'models': [
('admin', 'LogEntry'),
('auth', 'Group'),
('auth', 'Permission'),
('contenttypes', 'ContentType'),
('sessions', 'Session'),
],
},
```
**Benefits:**
- Logical grouping by functionality
- Emoji icons for quick visual recognition
- Combined Billing & Payments into one group
- Separated Content Management from Planning
- Grouped AI, Automation, and Optimization together
- Clearer hierarchy and easier navigation
### 1.4 Install Django Admin Enhancement Packages
**Packages to install:**
```bash
# UI Enhancement
pip install django-admin-interface # Modern, customizable theme
# OR
pip install django-grappelli # Alternative mature theme
# Functionality
pip install django-import-export # CSV/Excel import/export
pip install django-admin-rangefilter # Date range filters
pip install django-advanced-filters # Save filter combinations
pip install django-admin-autocomplete-filter # Better autocomplete
```
**Configuration needed:**
- Add to INSTALLED_APPS
- Configure static files
- Run collectstatic
- Apply migrations if needed
### 1.5 Basic UI Styling Improvements
**Without packages (quick wins):**
Create custom CSS file: `backend/igny8_core/static/admin/css/igny8_admin.css`
```css
/* Status badges */
.status-active { color: #28a745; font-weight: bold; }
.status-inactive { color: #dc3545; }
.status-pending { color: #ffc107; }
/* Credit indicators */
.credits-low { color: #dc3545; font-weight: bold; }
.credits-medium { color: #ffc107; }
.credits-high { color: #28a745; }
/* Quick action buttons */
.admin-action-button {
padding: 5px 15px;
border-radius: 4px;
cursor: pointer;
text-decoration: none;
display: inline-block;
margin: 2px;
}
/* List view enhancements */
.django-admin-index tr:hover {
background-color: #f8f9fa;
}
```
Add custom template: `backend/igny8_core/templates/admin/base_site.html`
```html
{% extends "admin/base.html" %}
{% load static %}
{% block title %}{{ title }} | IGNY8 Admin{% endblock %}
{% block branding %}
<h1 id="site-name">
<a href="{% url 'admin:index' %}">
IGNY8 Administration
</a>
</h1>
{% endblock %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'admin/css/igny8_admin.css' %}">
{% endblock %}
```
---
## Phase 2: Operational Features (Week 3-4)
### 2.1 Add Bulk Operations
**Priority Models for Bulk Actions:**
#### Tasks Admin
```python
actions = [
'bulk_set_status_draft',
'bulk_set_status_in_progress',
'bulk_set_status_completed',
'bulk_assign_cluster',
'bulk_generate_content',
'bulk_export_csv',
]
```
#### Content Admin
```python
actions = [
'bulk_publish_to_wordpress',
'bulk_set_status',
'bulk_add_taxonomy',
'bulk_export_with_seo',
]
```
#### Keywords Admin
```python
actions = [
'bulk_assign_cluster',
'bulk_set_priority',
'bulk_export_csv',
]
```
#### Payments Admin (already has some)
```python
actions = [
'approve_payments',
'reject_payments',
'export_transactions', # ADD
]
```
### 2.2 Implement CSV Export
**Install django-import-export:**
Add to each admin class:
```python
from import_export.admin import ExportMixin
class TasksAdmin(ExportMixin, SiteSectorAdminMixin, admin.ModelAdmin):
resource_class = TaskResource # Define export fields
# ... existing code
```
**Create Resource classes for key models:**
- TaskResource
- ContentResource
- KeywordsResource
- CreditTransactionResource
- PaymentResource
### 2.3 Advanced Filtering
**Add date range filters:**
```python
from rangefilter.filters import DateRangeFilter
class CreditTransactionAdmin(AccountAdminMixin, admin.ModelAdmin):
list_filter = [
'transaction_type',
('created_at', DateRangeFilter),
'account',
]
```
**Add autocomplete filters for large datasets:**
```python
class TasksAdmin(SiteSectorAdminMixin, admin.ModelAdmin):
autocomplete_fields = ['site', 'sector', 'cluster']
search_fields = ['title', 'description']
```
---
## Phase 3: Monitoring & Dashboards (Week 5-6)
### 3.1 Celery Task Monitoring
**Install django-celery-results:**
```bash
pip install django-celery-results
```
**Add to settings.py:**
```python
INSTALLED_APPS = [
# ...
'django_celery_results',
]
CELERY_RESULT_BACKEND = 'django-db'
CELERY_CACHE_BACKEND = 'django-cache'
```
**Create Celery Task Admin:**
File: `backend/igny8_core/admin/celery_admin.py`
```python
from django.contrib import admin
from django_celery_results.models import TaskResult
@admin.register(TaskResult)
class CeleryTaskResultAdmin(admin.ModelAdmin):
list_display = [
'task_id',
'task_name',
'status',
'date_created',
'date_done',
'colored_status',
]
list_filter = [
'status',
'task_name',
('date_created', DateRangeFilter),
]
search_fields = ['task_id', 'task_name', 'task_args']
readonly_fields = ['task_id', 'task_name', 'task_args', 'task_kwargs', 'result', 'traceback']
actions = ['retry_failed_tasks', 'clear_old_tasks']
def colored_status(self, obj):
colors = {
'SUCCESS': 'green',
'FAILURE': 'red',
'PENDING': 'orange',
'STARTED': 'blue',
}
color = colors.get(obj.status, 'gray')
return format_html(
'<span style="color: {}; font-weight: bold;">{}</span>',
color,
obj.status
)
colored_status.short_description = 'Status'
def retry_failed_tasks(self, request, queryset):
"""Retry failed celery tasks"""
from celery import current_app
count = 0
for task in queryset.filter(status='FAILURE'):
try:
# Get task function and retry
task_func = current_app.tasks.get(task.task_name)
if task_func:
task_func.apply_async()
count += 1
except Exception as e:
self.message_user(request, f'Error retrying task {task.task_id}: {str(e)}', level='ERROR')
self.message_user(request, f'Retried {count} failed task(s)', level='SUCCESS')
retry_failed_tasks.short_description = 'Retry failed tasks'
```
**Add to admin groups:**
```python
'🤖 AI & Automation': {
'models': [
# ...
('django_celery_results', 'TaskResult'),
],
},
```
### 3.2 Admin Dashboard with Metrics
**Create custom admin index view:**
File: `backend/igny8_core/admin/dashboard.py`
```python
from django.contrib.admin.views.decorators import staff_member_required
from django.shortcuts import render
from django.db.models import Count, Sum, Q
from django.utils import timezone
from datetime import timedelta
@staff_member_required
def admin_dashboard(request):
"""Custom admin dashboard with key metrics"""
# Date ranges
today = timezone.now().date()
week_ago = today - timedelta(days=7)
month_ago = today - timedelta(days=30)
# Account metrics
from igny8_core.auth.models import Account
total_accounts = Account.objects.count()
active_accounts = Account.objects.filter(status='active').count()
low_credit_accounts = Account.objects.filter(credits__lt=100).count()
# Content metrics
from igny8_core.modules.writer.models import Content, Tasks
content_this_week = Content.objects.filter(created_at__gte=week_ago).count()
content_this_month = Content.objects.filter(created_at__gte=month_ago).count()
tasks_pending = Tasks.objects.filter(status='pending').count()
# Billing metrics
from igny8_core.modules.billing.models import Payment, CreditTransaction
pending_payments = Payment.objects.filter(status='pending_approval').count()
payments_this_month = Payment.objects.filter(
created_at__gte=month_ago,
status='succeeded'
).aggregate(total=Sum('amount'))['total'] or 0
credit_usage_this_month = CreditTransaction.objects.filter(
created_at__gte=month_ago,
transaction_type='deduction'
).aggregate(total=Sum('amount'))['total'] or 0
# Automation metrics
from igny8_core.business.automation.models import AutomationRun
automation_running = AutomationRun.objects.filter(status='running').count()
automation_failed = AutomationRun.objects.filter(
status='failed',
created_at__gte=week_ago
).count()
# WordPress sync metrics
from igny8_core.business.integration.models import SyncEvent
sync_failed = SyncEvent.objects.filter(
success=False,
created_at__gte=today
).count()
context = {
'title': 'Dashboard',
'accounts': {
'total': total_accounts,
'active': active_accounts,
'low_credit': low_credit_accounts,
},
'content': {
'this_week': content_this_week,
'this_month': content_this_month,
'tasks_pending': tasks_pending,
},
'billing': {
'pending_payments': pending_payments,
'payments_this_month': payments_this_month,
'credit_usage_this_month': abs(credit_usage_this_month),
},
'automation': {
'running': automation_running,
'failed_this_week': automation_failed,
},
'integration': {
'sync_failed_today': sync_failed,
},
}
return render(request, 'admin/dashboard.html', context)
```
**Create dashboard template:**
File: `backend/igny8_core/templates/admin/dashboard.html`
```html
{% extends "admin/base_site.html" %}
{% load static %}
{% block content %}
<h1>IGNY8 Admin Dashboard</h1>
<div class="dashboard-grid">
<!-- Accounts Overview -->
<div class="dashboard-card">
<h2>👥 Accounts</h2>
<div class="metric-row">
<div class="metric">
<span class="metric-value">{{ accounts.total }}</span>
<span class="metric-label">Total Accounts</span>
</div>
<div class="metric">
<span class="metric-value status-active">{{ accounts.active }}</span>
<span class="metric-label">Active</span>
</div>
<div class="metric">
<span class="metric-value {% if accounts.low_credit > 0 %}credits-low{% endif %}">
{{ accounts.low_credit }}
</span>
<span class="metric-label">Low Credits (< 100)</span>
</div>
</div>
</div>
<!-- Content Production -->
<div class="dashboard-card">
<h2>📝 Content Production</h2>
<div class="metric-row">
<div class="metric">
<span class="metric-value">{{ content.this_week }}</span>
<span class="metric-label">This Week</span>
</div>
<div class="metric">
<span class="metric-value">{{ content.this_month }}</span>
<span class="metric-label">This Month</span>
</div>
<div class="metric">
<span class="metric-value status-pending">{{ content.tasks_pending }}</span>
<span class="metric-label">Tasks Pending</span>
</div>
</div>
</div>
<!-- Billing Overview -->
<div class="dashboard-card">
<h2>💰 Billing</h2>
<div class="metric-row">
<div class="metric">
<span class="metric-value {% if billing.pending_payments > 0 %}status-pending{% endif %}">
{{ billing.pending_payments }}
</span>
<span class="metric-label">Pending Approvals</span>
<a href="{% url 'admin:billing_payment_changelist' %}?status=pending_approval" class="metric-link">
Review →
</a>
</div>
<div class="metric">
<span class="metric-value">${{ billing.payments_this_month|floatformat:2 }}</span>
<span class="metric-label">Revenue This Month</span>
</div>
<div class="metric">
<span class="metric-value">{{ billing.credit_usage_this_month }}</span>
<span class="metric-label">Credits Used</span>
</div>
</div>
</div>
<!-- Automation Status -->
<div class="dashboard-card">
<h2>🤖 Automation</h2>
<div class="metric-row">
<div class="metric">
<span class="metric-value status-active">{{ automation.running }}</span>
<span class="metric-label">Running Now</span>
</div>
<div class="metric">
<span class="metric-value {% if automation.failed_this_week > 0 %}status-inactive{% endif %}">
{{ automation.failed_this_week }}
</span>
<span class="metric-label">Failed (7 days)</span>
{% if automation.failed_this_week > 0 %}
<a href="{% url 'admin:automation_automationrun_changelist' %}?status=failed" class="metric-link">
Review →
</a>
{% endif %}
</div>
</div>
</div>
<!-- Integration Health -->
<div class="dashboard-card">
<h2>🔗 Integration Health</h2>
<div class="metric-row">
<div class="metric">
<span class="metric-value {% if integration.sync_failed_today > 0 %}status-inactive{% endif %}">
{{ integration.sync_failed_today }}
</span>
<span class="metric-label">Failed Syncs Today</span>
{% if integration.sync_failed_today > 0 %}
<a href="{% url 'admin:integration_syncevent_changelist' %}?success=False" class="metric-link">
Review →
</a>
{% endif %}
</div>
</div>
</div>
</div>
<style>
.dashboard-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
}
.dashboard-card {
background: white;
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.dashboard-card h2 {
margin-top: 0;
border-bottom: 2px solid #417690;
padding-bottom: 10px;
}
.metric-row {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 15px;
}
.metric {
display: flex;
flex-direction: column;
min-width: 120px;
}
.metric-value {
font-size: 32px;
font-weight: bold;
color: #417690;
}
.metric-label {
font-size: 12px;
color: #666;
margin-top: 5px;
}
.metric-link {
font-size: 12px;
color: #417690;
text-decoration: none;
margin-top: 5px;
}
.metric-link:hover {
text-decoration: underline;
}
</style>
{% endblock %}
```
**Update admin site URLs:**
```python
# backend/igny8_core/admin/site.py
from .dashboard import admin_dashboard
class Igny8AdminSite(admin.AdminSite):
# ... existing code
def get_urls(self):
from django.urls import path
urls = super().get_urls()
custom_urls = [
path('dashboard/', self.admin_view(admin_dashboard), name='dashboard'),
]
return custom_urls + urls
def index(self, request, extra_context=None):
"""Redirect to custom dashboard"""
from django.shortcuts import redirect
return redirect('admin:dashboard')
```
### 3.3 Account Health Indicators
**Add to Account Admin:**
```python
@admin.register(Account)
class AccountAdmin(AccountAdminMixin, admin.ModelAdmin):
# ... existing code
list_display = [
'name',
'slug',
'owner',
'plan',
'status',
'credits',
'health_indicator', # ADD
'created_at'
]
def health_indicator(self, obj):
"""Visual health score"""
score = 100
issues = []
# Check credit balance
if obj.credits < 50:
score -= 30
issues.append('Low credits')
elif obj.credits < 100:
score -= 15
# Check recent activity
from django.utils import timezone
from datetime import timedelta
week_ago = timezone.now() - timedelta(days=7)
from igny8_core.modules.writer.models import Content
recent_content = Content.objects.filter(
account=obj,
created_at__gte=week_ago
).count()
if recent_content == 0:
score -= 20
issues.append('No recent activity')
# Check failed automations
from igny8_core.business.automation.models import AutomationRun
failed_runs = AutomationRun.objects.filter(
site__account=obj,
status='failed',
created_at__gte=week_ago
).count()
if failed_runs > 0:
score -= 15
issues.append(f'{failed_runs} failed automation(s)')
# Determine color
if score >= 80:
color = 'green'
icon = ''
elif score >= 60:
color = 'orange'
icon = '⚠️'
else:
color = 'red'
icon = ''
issue_text = ', '.join(issues) if issues else 'Healthy'
return format_html(
'<span style="color: {}; font-size: 18px;">{}</span> '
'<span style="color: {};">{}</span>',
color, icon, color, issue_text
)
health_indicator.short_description = 'Health'
```
### 3.4 Alert System
**Create alerts utility:**
File: `backend/igny8_core/admin/alerts.py`
```python
from django.core.cache import cache
from django.utils import timezone
from datetime import timedelta
class AdminAlerts:
"""System for admin alerts and notifications"""
@staticmethod
def get_alerts():
"""Get all active alerts"""
alerts = []
# Check for pending payments
from igny8_core.modules.billing.models import Payment
pending_payments = Payment.objects.filter(status='pending_approval').count()
if pending_payments > 0:
alerts.append({
'level': 'warning',
'message': f'{pending_payments} payment(s) awaiting approval',
'url': '/admin/billing/payment/?status=pending_approval',
'action': 'Review Payments'
})
# Check for low credit accounts
from igny8_core.auth.models import Account
low_credit_accounts = Account.objects.filter(
status='active',
credits__lt=100
).count()
if low_credit_accounts > 0:
alerts.append({
'level': 'info',
'message': f'{low_credit_accounts} account(s) with low credits',
'url': '/admin/igny8_core_auth/account/?credits__lt=100',
'action': 'View Accounts'
})
# Check for failed automations
from igny8_core.business.automation.models import AutomationRun
today = timezone.now().date()
failed_today = AutomationRun.objects.filter(
status='failed',
created_at__date=today
).count()
if failed_today > 0:
alerts.append({
'level': 'error',
'message': f'{failed_today} automation(s) failed today',
'url': '/admin/automation/automationrun/?status=failed',
'action': 'Review Failures'
})
# Check for failed syncs
from igny8_core.business.integration.models import SyncEvent
failed_syncs = SyncEvent.objects.filter(
success=False,
created_at__date=today
).count()
if failed_syncs > 5: # Only alert if more than 5
alerts.append({
'level': 'warning',
'message': f'{failed_syncs} WordPress sync failures today',
'url': '/admin/integration/syncevent/?success=False',
'action': 'Review Syncs'
})
return alerts
```
**Add to dashboard template:**
```html
<!-- Add after <h1>IGNY8 Admin Dashboard</h1> -->
{% if alerts %}
<div class="alerts-section">
{% for alert in alerts %}
<div class="alert alert-{{ alert.level }}">
<span class="alert-icon">
{% if alert.level == 'error' %}🔴{% endif %}
{% if alert.level == 'warning' %}⚠️{% endif %}
{% if alert.level == 'info' %}{% endif %}
</span>
<span class="alert-message">{{ alert.message }}</span>
<a href="{{ alert.url }}" class="alert-action">{{ alert.action }}</a>
</div>
{% endfor %}
</div>
{% endif %}
```
---
## Phase 4: Analytics & Reporting (Week 7-8)
### 4.1 Business Intelligence Reports
**Create reports module:**
File: `backend/igny8_core/admin/reports.py`
```python
from django.contrib.admin.views.decorators import staff_member_required
from django.shortcuts import render
from django.db.models import Count, Sum, Avg, Q
from django.utils import timezone
from datetime import timedelta
import json
@staff_member_required
def revenue_report(request):
"""Revenue and billing analytics"""
from igny8_core.modules.billing.models import Payment
from igny8_core.auth.models import Plan
# Date ranges
today = timezone.now()
months = []
monthly_revenue = []
for i in range(6):
month_start = today.replace(day=1) - timedelta(days=30*i)
month_end = month_start.replace(day=28) + timedelta(days=4)
revenue = Payment.objects.filter(
status='succeeded',
processed_at__gte=month_start,
processed_at__lt=month_end
).aggregate(total=Sum('amount'))['total'] or 0
months.insert(0, month_start.strftime('%b %Y'))
monthly_revenue.insert(0, float(revenue))
# Plan distribution
plan_distribution = Plan.objects.annotate(
account_count=Count('account')
).values('name', 'account_count')
# Payment method breakdown
payment_methods = Payment.objects.filter(
status='succeeded'
).values('payment_method').annotate(
count=Count('id'),
total=Sum('amount')
).order_by('-total')
context = {
'title': 'Revenue Report',
'months': json.dumps(months),
'monthly_revenue': json.dumps(monthly_revenue),
'plan_distribution': plan_distribution,
'payment_methods': payment_methods,
}
return render(request, 'admin/reports/revenue.html', context)
@staff_member_required
def usage_report(request):
"""Credit usage and AI operations analytics"""
from igny8_core.modules.billing.models import CreditUsageLog
# Usage by operation type
usage_by_operation = CreditUsageLog.objects.values(
'operation_type'
).annotate(
total_credits=Sum('credits_used'),
total_cost=Sum('cost_usd'),
operation_count=Count('id')
).order_by('-total_credits')
# Top credit consumers
from django.db.models import Count
top_consumers = CreditUsageLog.objects.values(
'account__name'
).annotate(
total_credits=Sum('credits_used'),
operation_count=Count('id')
).order_by('-total_credits')[:10]
# Model usage distribution
model_usage = CreditUsageLog.objects.values(
'model_used'
).annotate(
usage_count=Count('id')
).order_by('-usage_count')
context = {
'title': 'Usage Report',
'usage_by_operation': usage_by_operation,
'top_consumers': top_consumers,
'model_usage': model_usage,
}
return render(request, 'admin/reports/usage.html', context)
@staff_member_required
def content_report(request):
"""Content production analytics"""
from igny8_core.modules.writer.models import Content, Tasks
# Content by type
content_by_type = Content.objects.values(
'content_type'
).annotate(count=Count('id')).order_by('-count')
# Production timeline (last 30 days)
days = []
daily_counts = []
for i in range(30):
day = timezone.now().date() - timedelta(days=i)
count = Content.objects.filter(created_at__date=day).count()
days.insert(0, day.strftime('%m/%d'))
daily_counts.insert(0, count)
# Average word count by content type
avg_words = Content.objects.values('content_type').annotate(
avg_words=Avg('word_count')
).order_by('-avg_words')
# Task completion rate
total_tasks = Tasks.objects.count()
completed_tasks = Tasks.objects.filter(status='completed').count()
completion_rate = (completed_tasks / total_tasks * 100) if total_tasks > 0 else 0
context = {
'title': 'Content Production Report',
'content_by_type': content_by_type,
'days': json.dumps(days),
'daily_counts': json.dumps(daily_counts),
'avg_words': avg_words,
'completion_rate': completion_rate,
}
return render(request, 'admin/reports/content.html', context)
```
**Add report links to admin site:**
```python
# In Igny8AdminSite.get_urls()
custom_urls = [
path('dashboard/', self.admin_view(admin_dashboard), name='dashboard'),
path('reports/revenue/', self.admin_view(revenue_report), name='report_revenue'),
path('reports/usage/', self.admin_view(usage_report), name='report_usage'),
path('reports/content/', self.admin_view(content_report), name='report_content'),
]
```
### 4.2 Data Quality Dashboard
**Create data quality checker:**
```python
@staff_member_required
def data_quality_report(request):
"""Check data quality and integrity"""
issues = []
# Orphaned content (no site)
from igny8_core.modules.writer.models import Content
orphaned_content = Content.objects.filter(site__isnull=True).count()
if orphaned_content > 0:
issues.append({
'severity': 'warning',
'type': 'Orphaned Records',
'count': orphaned_content,
'description': 'Content items without assigned site',
'action_url': '/admin/writer/content/?site__isnull=True'
})
# Tasks without clusters
from igny8_core.modules.writer.models import Tasks
tasks_no_cluster = Tasks.objects.filter(cluster__isnull=True).count()
if tasks_no_cluster > 0:
issues.append({
'severity': 'info',
'type': 'Missing Relationships',
'count': tasks_no_cluster,
'description': 'Tasks without assigned cluster',
'action_url': '/admin/writer/tasks/?cluster__isnull=True'
})
# Accounts with negative credits
from igny8_core.auth.models import Account
negative_credits = Account.objects.filter(credits__lt=0).count()
if negative_credits > 0:
issues.append({
'severity': 'error',
'type': 'Data Integrity',
'count': negative_credits,
'description': 'Accounts with negative credit balance',
'action_url': '/admin/igny8_core_auth/account/?credits__lt=0'
})
# Duplicate keywords
from igny8_core.modules.planner.models import Keywords
from django.db.models import Count
duplicates = Keywords.objects.values('keyword', 'site', 'sector').annotate(
count=Count('id')
).filter(count__gt=1).count()
if duplicates > 0:
issues.append({
'severity': 'warning',
'type': 'Duplicates',
'count': duplicates,
'description': 'Duplicate keywords for same site/sector',
'action_url': '/admin/planner/keywords/'
})
# Content without SEO data
no_seo = Content.objects.filter(
Q(meta_title__isnull=True) | Q(meta_title='') |
Q(meta_description__isnull=True) | Q(meta_description='')
).count()
if no_seo > 0:
issues.append({
'severity': 'info',
'type': 'Incomplete Data',
'count': no_seo,
'description': 'Content missing SEO metadata',
'action_url': '/admin/writer/content/'
})
context = {
'title': 'Data Quality Report',
'issues': issues,
'total_issues': len(issues),
}
return render(request, 'admin/reports/data_quality.html', context)
```
---
## Phase 5: Advanced Features (Week 9-10)
### 5.1 Inline Editing
**Enable list_editable for common fields:**
```python
# Tasks Admin
class TasksAdmin(SiteSectorAdminMixin, admin.ModelAdmin):
list_editable = ['status', 'cluster'] # Quick edit in list view
# Keywords Admin
class KeywordsAdmin(SiteSectorAdminMixin, admin.ModelAdmin):
list_editable = ['cluster', 'status']
# Payment Admin - already has workflow, keep as-is
```
### 5.2 Enhanced Audit Trail
**Install django-simple-history:**
```bash
pip install django-simple-history
```
**Add to critical models:**
```python
from simple_history.models import HistoricalRecords
class Payment(models.Model):
# ... existing fields
history = HistoricalRecords()
class Account(AccountBaseModel):
# ... existing fields
history = HistoricalRecords()
class CreditCostConfig(models.Model):
# ... existing fields
history = HistoricalRecords()
```
**Register history admin:**
```python
from simple_history.admin import SimpleHistoryAdmin
@admin.register(Payment)
class PaymentAdmin(SimpleHistoryAdmin, AccountAdminMixin, admin.ModelAdmin):
# ... existing code
# This adds a "History" button to view all changes
```
### 5.3 Permission Groups
**Create permission groups:**
```python
# backend/igny8_core/management/commands/create_admin_groups.py
from django.core.management.base import BaseCommand
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
class Command(BaseCommand):
help = 'Create admin permission groups'
def handle(self, *args, **kwargs):
# Content Manager Group
content_manager, _ = Group.objects.get_or_create(name='Content Manager')
content_perms = Permission.objects.filter(
content_type__app_label__in=['writer', 'planner'],
codename__in=['view_content', 'change_content', 'view_tasks', 'change_tasks']
)
content_manager.permissions.set(content_perms)
# Billing Administrator Group
billing_admin, _ = Group.objects.get_or_create(name='Billing Administrator')
billing_perms = Permission.objects.filter(
content_type__app_label='billing'
)
billing_admin.permissions.set(billing_perms)
# Support Agent Group (Read-Only)
support_agent, _ = Group.objects.get_or_create(name='Support Agent')
support_perms = Permission.objects.filter(
codename__startswith='view_'
)
support_agent.permissions.set(support_perms)
self.stdout.write(self.style.SUCCESS('Successfully created admin groups'))
```
---
## Implementation Checklist
### Week 1-2: Critical Fixes & UI Foundation
- [ ] Remove unused site_building models from admin site config
- [ ] Remove duplicate model registrations (keep modules/ versions)
- [ ] Reorganize sidebar menu with emoji icons and logical groups
- [ ] Add PlanLimitUsage to Billing & Accounts group
- [ ] Install django-admin-interface or django-grappelli
- [ ] Configure admin theme package
- [ ] Create custom CSS file for status colors and basic styling
- [ ] Create custom base_site.html template
- [ ] Test admin UI improvements
- [ ] Document theme customization options
### Week 3-4: Operational Features
- [ ] Add bulk status update actions to Tasks admin
- [ ] Add bulk operations to Content admin
- [ ] Add bulk operations to Keywords admin
- [ ] Add export action to Payments admin
- [ ] Install django-import-export
- [ ] Create Resource classes for Tasks, Content, Keywords, Payments
- [ ] Add export buttons to admin list views
- [ ] Install django-admin-rangefilter
- [ ] Add date range filters to key models
- [ ] Configure autocomplete_fields for large foreign keys
- [ ] Test all bulk operations
- [ ] Test export functionality
### Week 5-6: Monitoring & Dashboards
- [ ] Install django-celery-results
- [ ] Configure Celery to use django-db backend
- [ ] Create CeleryTaskResultAdmin with colored status
- [ ] Add retry_failed_tasks action
- [ ] Create admin_dashboard view function
- [ ] Create dashboard.html template with metrics
- [ ] Add dashboard route to admin site URLs
- [ ] Redirect admin index to dashboard
- [ ] Add health_indicator to Account admin
- [ ] Create AdminAlerts utility class
- [ ] Add alerts section to dashboard template
- [ ] Add alert styling CSS
- [ ] Test dashboard metrics accuracy
- [ ] Test alert system functionality
### Week 7-8: Analytics & Reporting
- [ ] Create reports.py module
- [ ] Implement revenue_report view
- [ ] Implement usage_report view
- [ ] Implement content_report view
- [ ] Implement data_quality_report view
- [ ] Create report templates (revenue, usage, content, data_quality)
- [ ] Add chart.js or similar for visualizations
- [ ] Add report links to admin navigation
- [ ] Create report permission checks
- [ ] Test all reports with real data
- [ ] Optimize report queries for performance
### Week 9-10: Advanced Features
- [ ] Enable list_editable for Tasks and Keywords
- [ ] Install django-simple-history
- [ ] Add HistoricalRecords to Payment model
- [ ] Add HistoricalRecords to Account model
- [ ] Add HistoricalRecords to CreditCostConfig model
- [ ] Run migrations for history tables
- [ ] Update admins to use SimpleHistoryAdmin
- [ ] Create create_admin_groups management command
- [ ] Define permission groups (Content Manager, Billing Admin, Support Agent)
- [ ] Assign permissions to groups
- [ ] Test permission restrictions
- [ ] Document permission group usage
---
## Technical Requirements
### Python Packages
```txt
# Add to requirements.txt
django-admin-interface==0.26.0 # Modern admin theme
django-import-export==3.3.1 # CSV/Excel import/export
django-admin-rangefilter==0.11.1 # Date range filters
django-advanced-filters==2.4.0 # Saved filters
django-celery-results==2.5.1 # Celery monitoring
django-simple-history==3.4.0 # Audit trail
```
### Settings Configuration
```python
# backend/igny8_core/settings.py
INSTALLED_APPS = [
'admin_interface', # Must be before django.contrib.admin
'colorfield', # Required by admin_interface
'igny8_core.admin.apps.Igny8AdminConfig',
# ... rest of apps
'import_export',
'rangefilter',
'advanced_filters',
'django_celery_results',
'simple_history',
]
# Admin Interface Configuration
X_FRAME_OPTIONS = 'SAMEORIGIN' # Required for admin_interface
# Celery Results
CELERY_RESULT_BACKEND = 'django-db'
CELERY_CACHE_BACKEND = 'django-cache'
# History Middleware
MIDDLEWARE = [
# ... existing middleware
'simple_history.middleware.HistoryRequestMiddleware',
]
# Import/Export Settings
IMPORT_EXPORT_USE_TRANSACTIONS = True
```
### Database Migrations
```bash
# After adding packages
python manage.py migrate admin_interface
python manage.py migrate django_celery_results
python manage.py migrate simple_history
# Collect static files
python manage.py collectstatic --noinput
```
### Static Files Structure
```
backend/igny8_core/static/
├── admin/
│ ├── css/
│ │ └── igny8_admin.css
│ └── js/
│ └── igny8_admin.js
└── charts/
└── chart.min.js
```
### Template Structure
```
backend/igny8_core/templates/
├── admin/
│ ├── base_site.html
│ ├── dashboard.html
│ └── reports/
│ ├── revenue.html
│ ├── usage.html
│ ├── content.html
│ └── data_quality.html
```
---
## Testing Plan
### Manual Testing Checklist
- [ ] Admin login works
- [ ] Dashboard displays correctly
- [ ] All sidebar groups show correct models
- [ ] No 404 errors for any admin links
- [ ] Bulk actions work on all enabled models
- [ ] CSV export generates valid files
- [ ] Date range filters work correctly
- [ ] Autocomplete fields load data
- [ ] Celery task monitoring shows tasks
- [ ] Dashboard metrics are accurate
- [ ] Alerts show for real issues
- [ ] Reports generate without errors
- [ ] Charts render correctly
- [ ] History tracking works for enabled models
- [ ] Permission groups restrict access correctly
### Performance Testing
- [ ] Dashboard loads in < 2 seconds
- [ ] List views with 1000+ records paginate correctly
- [ ] Bulk operations on 100+ records complete
- [ ] Export of 1000+ records completes
- [ ] Reports with large datasets load within 5 seconds
- [ ] No N+1 query issues in list views
---
## Rollback Plan
If issues arise during implementation:
1. **Theme Issues:** Revert to default Django admin
```bash
# Remove from INSTALLED_APPS
# 'admin_interface',
python manage.py migrate admin_interface zero
```
2. **Duplicate Registration Issues:**
- Keep `modules/` admin files active
- Comment out `business/` admin registrations
3. **Performance Issues:**
- Disable expensive dashboard queries
- Use caching for metrics
- Reduce pagination size
4. **Database Issues:**
- All migrations are reversible
- Backup before major changes
- Test on staging first
---
## Success Metrics
Track these metrics to measure improvement success:
1. **Time Savings**
- Payment approval time: Target < 2 minutes
- Content review time: Target < 5 minutes per item
- Report generation time: Target < 30 seconds
2. **User Satisfaction**
- Admin user feedback: Target 8+/10
- Feature usage: 80%+ of new features used weekly
3. **Data Quality**
- Orphaned records: Reduce by 90%
- Duplicate data: Reduce by 80%
- Data completeness: Increase to 95%+
4. **Operational Efficiency**
- Failed automation detection: < 1 hour
- Payment processing: Same-day completion
- Account health monitoring: 100% visibility
---
## Maintenance & Support
### Regular Maintenance Tasks
- **Weekly:**
- Review dashboard alerts
- Check failed celery tasks
- Monitor data quality issues
- **Monthly:**
- Review permission group assignments
- Update credit cost configs if needed
- Clean up old celery task results
- Archive old audit logs
- **Quarterly:**
- Review and optimize slow admin queries
- Update admin theme if needed
- Review and update permission groups
- Analyze usage patterns for improvements
### Documentation Updates
Keep these docs updated:
- Admin user guide with new features
- Permission group definitions
- Report interpretation guides
- Troubleshooting common issues
---
## Future Enhancements (Post-Launch)
1. **AI-Powered Insights**
- Anomaly detection in usage patterns
- Predictive account churn analysis
- Automated optimization recommendations
2. **Advanced Automation**
- Workflow builder for common tasks
- Scheduled report delivery
- Auto-responses to common issues
3. **Mobile Admin**
- Responsive mobile design
- Mobile-optimized dashboards
- Push notifications for critical alerts
4. **Integration Enhancements**
- Slack/Discord alert integration
- Zapier/Make.com workflow triggers
- API for external admin tools
---
## Conclusion
This comprehensive plan transforms the Django admin from a basic management tool into a powerful operational hub. The phased approach ensures steady progress while minimizing disruption. Focus on Phases 1-3 for immediate operational impact, then expand to analytics and advanced features in Phases 4-5.
**Estimated Total Effort:** 4-6 weeks with 1-2 developers
**Priority:** 🔴 High - Critical for efficient operations at scale
**Dependencies:** Should be implemented after Plan Management (#2) is complete