# Django Admin Improvement Plan - Unfold Edition **Version:** 2.0.0 **Created:** December 14, 2025 **Status:** Implementation Phase **Priority:** 🔴 High - 3-4 weeks implementation **Dependencies:** After Plan Management Implementation **Theme:** Django Unfold (Modern Admin Theme) --- ## 🔧 CRITICAL FIXES APPLIED (December 14, 2025) ### Problem: Multiple Conflicting Admin Systems The system had **3 conflicting admin systems running simultaneously**: 1. Default Django admin 2. Custom IGNY8 admin modifications 3. Unfold theme (partially installed) This caused style conflicts, crashes, and inconsistent UI. ### Solution: Clean Unfold-Only Installation **✅ Fixed Issues:** 1. **Backend Container Crashing** - Missing `unfold` module - Added `django-unfold==0.73.1` to requirements.txt - Rebuilt Docker image: `igny8-backend:latest` - All containers now use new image (backend, celery_worker, celery_beat, flower) 2. **Admin Apps Configuration Error** - `AttributeError: module 'django.contrib.admin' has no attribute 'apps'` - Fixed import in `admin/apps.py`: `from django.contrib.admin.apps import AdminConfig` - Import Unfold AFTER apps are ready in `ready()` method 3. **Admin Site Inheritance** - Mixed admin systems - Changed `Igny8AdminSite` from `admin.AdminSite` → `UnfoldAdminSite` - All admin classes now inherit from Unfold's `ModelAdmin` 4. **Celery Admin Filters** - Using wrong filter classes - Changed from `DateRangeFilter` → `RangeDateFilter` (Unfold version) - Updated `CeleryTaskResultAdmin` to use `ModelAdmin` from Unfold 5. **Middleware Configuration** - Added `simple_history.middleware.HistoryRequestMiddleware` 6. **INSTALLED_APPS Order** - Unfold apps MUST be before `django.contrib.admin` - Configured properly in settings.py **✅ Result: Single Clean Admin System** - **ONLY Unfold** - No more conflicts - Modern, responsive UI with Tailwind CSS - Dark mode support - Advanced filters and bulk operations built-in - All containers running healthy --- ## Executive Summary This document outlines a comprehensive improvement plan for the IGNY8 Django Admin interface using **Django Unfold**, a modern, feature-rich admin theme. Unfold provides a beautiful UI based on Tailwind CSS, advanced filtering, bulk operations, dark mode, and extensive customization options - eliminating the need for custom CSS/JS while providing enterprise-grade functionality out of the box. **Key Objectives:** - ✅ **COMPLETED:** Install and configure Unfold theme - Leverage Unfold's built-in features for UI/UX excellence - Reorganize sidebar menu using Unfold's navigation system - Remove unused/empty models - Implement bulk operations with Unfold's action system - Add Celery task monitoring with Unfold integration - Create operational dashboards using Unfold's dashboard tools - Implement advanced filtering with Unfold's filter extensions **What Makes This Different:** - **Modern UI Out-of-the-Box:** No custom CSS needed - Unfold provides beautiful, responsive design - **Built-in Features:** Bulk operations, advanced filters, charts, dark mode included - **Django Integration:** Works seamlessly with django-import-export, django-simple-history, django-celery-results - **Extensible:** Easy to customize with Unfold's configuration system --- ## Current State Analysis ### ✅ Completed (Phase 0) - December 14, 2025 1. ✅ **Unfold Installation** - django-unfold==0.73.1 installed in requirements.txt 2. ✅ **Docker Image Rebuilt** - igny8-backend:latest rebuilt with all dependencies 3. ✅ **Settings Configuration** - UNFOLD settings configured in settings.py 4. ✅ **Admin Site Update** - Igny8AdminSite now inherits from UnfoldAdminSite 5. ✅ **Admin Apps Fixed** - Igny8AdminConfig properly imports Unfold after apps ready 6. ✅ **Celery Admin Updated** - CeleryTaskResultAdmin uses Unfold ModelAdmin & filters 7. ✅ **Supporting Packages** - django-simple-history, django-import-export, django-celery-results installed 8. ✅ **Middleware Updated** - simple_history.middleware.HistoryRequestMiddleware added 9. ✅ **Static Files** - Unfold assets collected via collectstatic 10. ✅ **All Containers Running** - Backend, Celery Worker, Celery Beat, Flower all healthy 11. ✅ **Conflicts Resolved** - No more mixed admin systems (default + custom + Unfold) 12. ✅ **Single Admin System** - **Unfold ONLY** - clean, modern, no conflicts ### ✅ Strengths 1. **Modern UI Theme** - Unfold provides beautiful, responsive Tailwind-based design 2. **Custom Admin Site** - Igny8AdminSite with logical grouping (maintained) 3. **Multi-Tenancy Support** - AccountAdminMixin and SiteSectorAdminMixin 4. **Payment Approval Workflow** - Comprehensive payment approval system 5. **Custom Actions** - API key generation, payment approval/rejection 6. **Field Customization** - Custom fieldsets and readonly fields ### âš ī¸ Issues Remaining #### 1. **Sidebar Menu Organization** - ✅ Current get_app_list() structure works but can be enhanced with Unfold features - Need to add icons to models for better visual recognition - Missing PlanLimitUsage model (needs to be added) - Some empty groups appearing #### 2. **Unused/Empty Models** (Same as before) - **site_building** models referenced but don't exist - Duplicate model registrations need cleanup #### 3. **Missing Features** (Now easier with Unfold) - CSV/Excel export - Can use Unfold's import_export integration - Bulk operations - Use Unfold's enhanced action system - Celery monitoring - Use Unfold's contrib package for better UI - Admin dashboard - Use Unfold's dashboard widgets - Advanced filtering - Use Unfold's filter contrib package --- ## Unfold Features Available ### Built-in Features We'll Use: 1. **Visual Interface** - Modern Tailwind CSS-based design - Dark mode support (automatic) - Responsive layout (mobile-friendly) - Beautiful forms and tables 2. **Advanced Filtering** - `unfold.contrib.filters` - Enhanced filter UI - Date range filters with calendar - Autocomplete filters for foreign keys - Numeric range filters 3. **Import/Export** - `unfold.contrib.import_export` - Styled import/export UI - Works seamlessly with django-import-export - Beautiful file upload/download interface 4. **History/Audit Trail** - `unfold.contrib.simple_history` - Enhanced history UI - Timeline view of changes - User attribution and timestamps 5. **Actions** - Enhanced bulk actions UI - Custom action styling - Progress indicators 6. **Dashboard Components** - Cards for metrics - Charts (Chart.js integration) - Custom widgets - Activity feeds 7. **Other Features** - Inline tabs for grouping - Conditional field visibility - WYSIWYG editor (Trix) - Sortable inlines - Command palette (Cmd+K search) --- ## Phase 1: Critical Fixes & Model Updates (Week 1) ### 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 Update Admin Classes to Use Unfold **Current State:** Most admin classes inherit from `admin.ModelAdmin` **Action:** Update all admin classes to inherit from Unfold's ModelAdmin: ```python from unfold.admin import ModelAdmin from unfold.contrib.filters.admin import RangeDateFilter from unfold.contrib.import_export.forms import ExportForm, ImportForm class TasksAdmin(SiteSectorAdminMixin, ModelAdmin): # Unfold-specific features compressed_fields = True # Compact form layout warn_unsaved_form = True # Warn before leaving unsaved form # Standard Django admin list_display = ['title', 'status', 'cluster', 'created_at'] list_filter = [ ('created_at', RangeDateFilter), # Unfold date range filter 'status', ] search_fields = ['title', 'description'] actions_detail = ['generate_content', 'assign_cluster'] # Actions in detail view ``` **Key Files to Update:** - `/data/app/igny8/backend/igny8_core/modules/writer/admin.py` - `/data/app/igny8/backend/igny8_core/modules/planner/admin.py` - `/data/app/igny8/backend/igny8_core/modules/billing/admin.py` - `/data/app/igny8/backend/igny8_core/business/automation/admin.py` - `/data/app/igny8/backend/igny8_core/business/integration/admin.py` - All other admin files ### 1.4 Add Model Icons for Visual Navigation **Action:** Add icon declarations to each admin class using Unfold's icon system (Material Symbols): ```python class AccountAdmin(AccountAdminMixin, ModelAdmin): # Add icon for sidebar icon = "business" # Material symbol name class ContentAdmin(SiteSectorAdminMixin, ModelAdmin): icon = "article" class TasksAdmin(SiteSectorAdminMixin, ModelAdmin): icon = "task" ``` **Icon Mapping:** | Model | Icon | Material Symbol | |-------|------|----------------| | Account | business | Business/company icon | | Plan | card_membership | Membership card | | Site | language | Globe/website icon | | User | person | Person icon | | Content | article | Article/document | | Tasks | task | Checkbox list | | Clusters | bubble_chart | Cluster diagram | | Keywords | vpn_key | Key icon | | Payment | payment | Payment icon | | Invoice | receipt | Receipt icon | | Automation | settings_suggest | Automation gear | | Integration | integration_instructions | Integration icon | ### 1.5 Configure Unfold Colors and Branding **Already Done:** Basic UNFOLD configuration in settings.py **Additional Customization:** ```python # In settings.py UNFOLD dict "SITE_FAVICONS": [ { "rel": "icon", "sizes": "32x32", "type": "image/png", "href": lambda request: static("favicons/favicon-32x32.png"), }, ], "SIDEBAR": { "show_search": True, "show_all_applications": True, "navigation": None, # Use get_app_list() from Igny8AdminSite }, "THEME": "light", # or "dark" or "auto" ``` --- ## Phase 2: Bulk Operations & Export (Week 2) ### 2.1 Implement CSV/Excel Export with Unfold **Install Already Complete:** django-import-export and unfold.contrib.import_export **Action:** Add ExportMixin and ImportMixin to admin classes: ```python from import_export.admin import ImportExportModelAdmin from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm class TasksAdmin(SiteSectorAdminMixin, ImportExportModelAdmin, ModelAdmin): import_form_class = ImportForm export_form_class = ExportForm # Define what fields to export class TaskResource(resources.ModelResource): class Meta: model = Tasks fields = ('id', 'title', 'status', 'cluster__name', 'site__name', 'created_at') export_order = fields resource_class = TaskResource ``` **Priority Models for Export:** - ✅ Tasks - ✅ Content - ✅ Keywords - ✅ Payments - ✅ CreditTransactions - ✅ Clusters ### 2.2 Add Bulk Operations with Unfold Actions **Unfold provides enhanced action UI automatically** **Action:** Add actions to admin classes: ```python from django.contrib import admin from unfold.decorators import action class TasksAdmin(SiteSectorAdminMixin, ModelAdmin): actions = ['bulk_set_in_progress', 'bulk_set_completed', 'bulk_assign_cluster'] @action(description="Mark as In Progress") def bulk_set_in_progress(self, request, queryset): updated = queryset.update(status='in_progress') self.message_user(request, f'{updated} tasks marked as in progress', 'SUCCESS') @action(description="Mark as Completed") def bulk_set_completed(self, request, queryset): updated = queryset.update(status='completed') self.message_user(request, f'{updated} tasks completed', 'SUCCESS') @action(description="Assign to Cluster", form_class=BulkAssignClusterForm) def bulk_assign_cluster(self, request, queryset): # Unfold will show form with cluster selection if 'cluster' in request.POST: cluster_id = request.POST['cluster'] queryset.update(cluster_id=cluster_id) self.message_user(request, f'Assigned to cluster', 'SUCCESS') ``` **Bulk Actions to Add:** #### Tasks Admin - Mark as Draft - Mark as In Progress - Mark as Completed - Assign to Cluster - Generate Content (trigger AI) #### Content Admin - Publish to WordPress - Change Status - Add Taxonomy - Update SEO Settings #### Keywords Admin - Assign to Cluster - Set Priority - Mark for Research #### Payments Admin - Approve Payments (already exists) - Reject Payments (already exists) - Export Transactions (add) ### 2.3 Advanced Filtering with Unfold **Unfold provides beautiful filter UI out of the box** **Action:** Use Unfold's filter contrib for enhanced filtering: ```python from unfold.contrib.filters.admin import ( RangeDateFilter, RangeDateTimeFilter, RangeNumericFilter, SingleNumericFilter, SliderNumericFilter, ) from unfold.contrib.filters.admin import RelatedDropdownFilter, ChoicesDropdownFilter class CreditTransactionAdmin(AccountAdminMixin, ModelAdmin): list_filter = [ ('created_at', RangeDateFilter), # Beautiful date range picker ('amount', RangeNumericFilter), # Numeric range with slider ('account', RelatedDropdownFilter), # Dropdown with search ('transaction_type', ChoicesDropdownFilter), # Enhanced dropdown ] ``` **Filter Types to Implement:** | Model | Filters | |-------|---------| | CreditTransaction | Date range, Amount range, Account dropdown, Type | | Payment | Date range, Status, Amount range, Method | | Content | Date range, Status, Site, Sector, Word count range | | Tasks | Date range, Status, Cluster, Priority | | AutomationRun | Date range, Status, Site, Success/Fail | --- ## 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( '{}', 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 %}

IGNY8 Admin Dashboard

đŸ‘Ĩ Accounts

{{ accounts.total }} Total Accounts
{{ accounts.active }} Active
{{ accounts.low_credit }} Low Credits (< 100)

📝 Content Production

{{ content.this_week }} This Week
{{ content.this_month }} This Month
{{ content.tasks_pending }} Tasks Pending

💰 Billing

{{ billing.pending_payments }} Pending Approvals Review →
${{ billing.payments_this_month|floatformat:2 }} Revenue This Month
{{ billing.credit_usage_this_month }} Credits Used

🤖 Automation

{{ automation.running }} Running Now
{{ automation.failed_this_week }} Failed (7 days) {% if automation.failed_this_week > 0 %} Review → {% endif %}

🔗 Integration Health

{{ integration.sync_failed_today }} Failed Syncs Today {% if integration.sync_failed_today > 0 %} Review → {% endif %}
{% 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( '{} ' '{}', 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 {% if alerts %}
{% for alert in alerts %}
{% if alert.level == 'error' %}🔴{% endif %} {% if alert.level == 'warning' %}âš ī¸{% endif %} {% if alert.level == 'info' %}â„šī¸{% endif %} {{ alert.message }} {{ alert.action }}
{% endfor %}
{% 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