diff --git a/DJANGO-ADMIN-IMPROVEMENT-PLAN.md b/DJANGO-ADMIN-IMPROVEMENT-PLAN.md
new file mode 100644
index 00000000..b08c8869
--- /dev/null
+++ b/DJANGO-ADMIN-IMPROVEMENT-PLAN.md
@@ -0,0 +1,1624 @@
+# 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 %}
+
+{% endblock %}
+
+{% block extrastyle %}
+ {{ block.super }}
+
+{% 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(
+ '{}',
+ 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
+
+
+
diff --git a/backend/igny8_core/admin/site.py b/backend/igny8_core/admin/site.py
index b046d37d..4feb7d76 100644
--- a/backend/igny8_core/admin/site.py
+++ b/backend/igny8_core/admin/site.py
@@ -23,57 +23,42 @@ class Igny8AdminSite(admin.AdminSite):
def get_app_list(self, request):
"""
- Customize the app list to organize models into proper groups
+ Customize the app list to organize models into logical groups
"""
# Get the default app list
app_dict = self._build_app_dict(request)
# Define our custom groups with their models (using object_name)
+ # Organized by business function with emoji icons for visual recognition
custom_groups = {
- 'Billing & Tenancy': {
+ 'đ° Billing & Accounts': {
'models': [
('igny8_core_auth', 'Plan'),
('igny8_core_auth', 'Account'),
('igny8_core_auth', 'Subscription'),
- ('billing', 'CreditTransaction'),
- ('billing', 'CreditUsageLog'),
('billing', 'Invoice'),
('billing', 'Payment'),
+ ('billing', 'CreditTransaction'),
+ ('billing', 'CreditUsageLog'),
('billing', 'CreditPackage'),
+ ('billing', 'PaymentMethodConfig'),
+ ('billing', 'AccountPaymentMethod'),
('billing', 'CreditCostConfig'),
],
},
- 'Sites & Users': {
+ 'đĨ Sites & Users': {
'models': [
('igny8_core_auth', 'Site'),
+ ('igny8_core_auth', 'Sector'),
('igny8_core_auth', 'User'),
('igny8_core_auth', 'SiteUserAccess'),
('igny8_core_auth', 'PasswordResetToken'),
- ('igny8_core_auth', 'Sector'),
],
},
- 'Global Reference Data': {
+ 'đ Content Management': {
'models': [
- ('igny8_core_auth', 'Industry'),
- ('igny8_core_auth', 'IndustrySector'),
- ('igny8_core_auth', 'SeedKeyword'),
- ('site_building', 'BusinessType'),
- ('site_building', 'AudienceProfile'),
- ('site_building', 'BrandPersonality'),
- ('site_building', 'HeroImageryDirection'),
- ],
- },
- 'Planner': {
- 'models': [
- ('planner', 'Keywords'),
- ('planner', 'Clusters'),
- ('planner', 'ContentIdeas'),
- ],
- },
- 'Writer Module': {
- 'models': [
- ('writer', 'Tasks'),
('writer', 'Content'),
+ ('writer', 'Tasks'),
('writer', 'Images'),
('writer', 'ContentTaxonomy'),
('writer', 'ContentAttribute'),
@@ -81,54 +66,53 @@ class Igny8AdminSite(admin.AdminSite):
('writer', 'ContentClusterMap'),
],
},
- 'Thinker Module': {
+ 'đ¯ Planning & Strategy': {
'models': [
- ('system', 'AIPrompt'),
- ('system', 'AuthorProfile'),
+ ('planner', 'Clusters'),
+ ('planner', 'Keywords'),
+ ('planner', 'ContentIdeas'),
('system', 'Strategy'),
- ('ai', 'AITaskLog'),
],
},
- 'System Configuration': {
+ 'đ 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', 'SystemLog'),
- ('system', 'SystemStatus'),
+ ('system', 'AuthorProfile'),
('system', 'SystemSettings'),
('system', 'AccountSettings'),
('system', 'UserSettings'),
('system', 'ModuleSettings'),
('system', 'AISettings'),
('system', 'ModuleEnableSettings'),
- # Automation config lives under the automation app - include here
- ('automation', 'AutomationConfig'),
- ('automation', 'AutomationRun'),
+ ('system', 'SystemLog'),
+ ('system', 'SystemStatus'),
],
},
- 'Payments': {
- 'models': [
- ('billing', 'PaymentMethodConfig'),
- ('billing', 'AccountPaymentMethod'),
- ],
- },
- 'Integrations & Sync': {
- 'models': [
- ('integration', 'SiteIntegration'),
- ('integration', 'SyncEvent'),
- ],
- },
- 'Publishing': {
- 'models': [
- ('publishing', 'PublishingRecord'),
- ('publishing', 'DeploymentRecord'),
- ],
- },
- 'Optimization': {
- 'models': [
- ('optimization', 'OptimizationTask'),
- ],
- },
- 'Django Internals': {
+ 'đ§ Django System': {
'models': [
('admin', 'LogEntry'),
('auth', 'Group'),
@@ -159,7 +143,7 @@ class Igny8AdminSite(admin.AdminSite):
if group_models:
app_list.append({
'name': group_name,
- 'app_label': group_name.lower().replace(' ', '_').replace('&', ''),
+ 'app_label': group_name.lower().replace(' ', '_').replace('&', '').replace('emoji', ''),
'app_url': None,
'has_module_perms': True,
'models': group_models,
@@ -167,18 +151,15 @@ class Igny8AdminSite(admin.AdminSite):
# Sort the app list by our custom order
order = [
- 'Billing & Tenancy',
- 'Sites & Users',
- 'Global Reference Data',
- 'Planner',
- 'Writer Module',
- 'Thinker Module',
- 'System Configuration',
- 'Payments',
- 'Integrations & Sync',
- 'Publishing',
- 'Optimization',
- 'Django Internals',
+ 'đ° Billing & Accounts',
+ 'đĨ Sites & Users',
+ 'đ Content Management',
+ 'đ¯ Planning & Strategy',
+ 'đ Integrations & Publishing',
+ 'đ¤ AI & Automation',
+ 'đ Global Reference Data',
+ 'âī¸ System Configuration',
+ 'đ§ Django System',
]
app_list.sort(key=lambda x: order.index(x['name']) if x['name'] in order else 999)
diff --git a/backend/igny8_core/business/billing/admin.py b/backend/igny8_core/business/billing/admin.py
index f2f0864a..b92780f0 100644
--- a/backend/igny8_core/business/billing/admin.py
+++ b/backend/igny8_core/business/billing/admin.py
@@ -1,5 +1,8 @@
"""
Billing Business Logic Admin
+
+NOTE: Most billing models are registered in modules/billing/admin.py
+with full workflow functionality. This file contains legacy/minimal registrations.
"""
from django.contrib import admin
from django.utils.html import format_html
@@ -14,133 +17,36 @@ from .models import (
)
-@admin.register(CreditCostConfig)
-class CreditCostConfigAdmin(admin.ModelAdmin):
- list_display = [
- 'operation_type',
- 'display_name',
- 'credits_cost_display',
- 'unit',
- 'is_active',
- 'cost_change_indicator',
- 'updated_at',
- 'updated_by'
- ]
-
- list_filter = ['is_active', 'unit', 'updated_at']
- search_fields = ['operation_type', 'display_name', 'description']
-
- fieldsets = (
- ('Operation', {
- 'fields': ('operation_type', 'display_name', 'description')
- }),
- ('Cost Configuration', {
- 'fields': ('credits_cost', 'unit', 'is_active')
- }),
- ('Audit Trail', {
- 'fields': ('previous_cost', 'updated_by', 'created_at', 'updated_at'),
- 'classes': ('collapse',)
- }),
- )
-
- readonly_fields = ['created_at', 'updated_at', 'previous_cost']
-
- def credits_cost_display(self, obj):
- """Show cost with color coding"""
- if obj.credits_cost >= 20:
- color = 'red'
- elif obj.credits_cost >= 10:
- color = 'orange'
- else:
- color = 'green'
- return format_html(
- '{} credits',
- color,
- obj.credits_cost
- )
- credits_cost_display.short_description = 'Cost'
-
- def cost_change_indicator(self, obj):
- """Show if cost changed recently"""
- if obj.previous_cost is not None:
- if obj.credits_cost > obj.previous_cost:
- icon = 'đ' # Increased
- color = 'red'
- elif obj.credits_cost < obj.previous_cost:
- icon = 'đ' # Decreased
- color = 'green'
- else:
- icon = 'âĄī¸' # Same
- color = 'gray'
-
- return format_html(
- '{} ({} â {})',
- icon,
- color,
- obj.previous_cost,
- obj.credits_cost
- )
- return 'â'
- cost_change_indicator.short_description = 'Recent Change'
-
- def save_model(self, request, obj, form, change):
- """Track who made the change"""
- obj.updated_by = request.user
- super().save_model(request, obj, form, change)
+# CreditCostConfig - DUPLICATE - Registered in modules/billing/admin.py with better features
+# Commenting out to avoid conflicts
+# @admin.register(CreditCostConfig)
+# class CreditCostConfigAdmin(admin.ModelAdmin):
+# ...existing implementation...
-@admin.register(Invoice)
-class InvoiceAdmin(AccountAdminMixin, admin.ModelAdmin):
- list_display = [
- 'invoice_number',
- 'account',
- 'status',
- 'total',
- 'currency',
- 'invoice_date',
- 'due_date',
- 'subscription',
- ]
- list_filter = ['status', 'currency', 'invoice_date', 'account']
- search_fields = ['invoice_number', 'account__name', 'subscription__id']
- readonly_fields = ['created_at', 'updated_at']
+# Invoice - DUPLICATE - Registered in modules/billing/admin.py
+# Commenting out to avoid conflicts
+# @admin.register(Invoice)
+# class InvoiceAdmin(AccountAdminMixin, admin.ModelAdmin):
+# ...existing implementation...
-@admin.register(Payment)
-class PaymentAdmin(AccountAdminMixin, admin.ModelAdmin):
- \"\"\"
- Payment admin - DO NOT USE.
- Use the Payment admin in modules/billing/admin.py which has approval workflow actions.
- This is kept for backward compatibility only.
- \"\"\"
- list_display = [
- 'id',
- 'invoice',
- 'account',
- 'payment_method',
- 'status',
- 'amount',
- 'currency',
- 'processed_at',
- ]
- list_filter = ['status', 'payment_method', 'currency', 'created_at']
- search_fields = ['invoice__invoice_number', 'account__name', 'stripe_payment_intent_id', 'paypal_order_id']
- readonly_fields = ['created_at', 'updated_at']
-
- def has_add_permission(self, request):\n return False # Prevent creating payments here
- \n def has_delete_permission(self, request, obj=None):\n return False # Prevent deleting payments here
+# Payment - DUPLICATE - Registered in modules/billing/admin.py with full approval workflow
+# Commenting out to avoid conflicts
+# @admin.register(Payment)
+# class PaymentAdmin(AccountAdminMixin, admin.ModelAdmin):
+# ...existing implementation...
-@admin.register(CreditPackage)
-class CreditPackageAdmin(admin.ModelAdmin):
- list_display = ['name', 'slug', 'credits', 'price', 'discount_percentage', 'is_active', 'is_featured', 'sort_order']
- list_filter = ['is_active', 'is_featured']
- search_fields = ['name', 'slug']
- readonly_fields = ['created_at', 'updated_at']
+# CreditPackage - DUPLICATE - Registered in modules/billing/admin.py
+# Commenting out to avoid conflicts
+# @admin.register(CreditPackage)
+# class CreditPackageAdmin(admin.ModelAdmin):
+# ...existing implementation...
-# PaymentMethodConfig admin is in modules/billing/admin.py - do not duplicate
-# @admin.register(PaymentMethodConfig)
+# PaymentMethodConfig and AccountPaymentMethod are kept here as they're not duplicated
+# or have minimal implementations that don't conflict
@admin.register(AccountPaymentMethod)
class AccountPaymentMethodAdmin(admin.ModelAdmin):
diff --git a/backend/igny8_core/static/admin/css/igny8_admin.css b/backend/igny8_core/static/admin/css/igny8_admin.css
new file mode 100644
index 00000000..f0726f32
--- /dev/null
+++ b/backend/igny8_core/static/admin/css/igny8_admin.css
@@ -0,0 +1,290 @@
+/* IGNY8 Custom Admin Styles */
+
+/* Status badges */
+.status-active {
+ color: #28a745 !important;
+ font-weight: bold;
+}
+
+.status-inactive {
+ color: #dc3545 !important;
+}
+
+.status-pending {
+ color: #ffc107 !important;
+ font-weight: bold;
+}
+
+.status-succeeded, .status-completed {
+ color: #28a745 !important;
+}
+
+.status-failed, .status-error {
+ color: #dc3545 !important;
+}
+
+/* Credit indicators */
+.credits-low {
+ color: #dc3545 !important;
+ font-weight: bold;
+}
+
+.credits-medium {
+ color: #ffc107 !important;
+}
+
+.credits-high {
+ color: #28a745 !important;
+}
+
+/* Quick action buttons */
+.admin-action-button {
+ padding: 5px 15px;
+ border-radius: 4px;
+ cursor: pointer;
+ text-decoration: none;
+ display: inline-block;
+ margin: 2px;
+ background-color: #417690;
+ color: white;
+ border: none;
+}
+
+.admin-action-button:hover {
+ background-color: #305d75;
+ color: white;
+ text-decoration: none;
+}
+
+/* List view enhancements */
+#content-main table tr:hover {
+ background-color: #f8f9fa !important;
+}
+
+/* Improve sidebar menu appearance */
+#content-related h3 {
+ background: #417690;
+ color: white;
+ padding: 10px;
+ border-radius: 4px 4px 0 0;
+}
+
+/* Better form field spacing */
+.form-row {
+ padding: 10px;
+}
+
+/* Highlight required fields */
+.required label:after {
+ content: " *";
+ color: #dc3545;
+}
+
+/* Success messages */
+.success, .messagelist .success {
+ background-color: #d4edda !important;
+ border-color: #c3e6cb !important;
+ color: #155724 !important;
+}
+
+/* Warning messages */
+.warning, .messagelist .warning {
+ background-color: #fff3cd !important;
+ border-color: #ffeaa7 !important;
+ color: #856404 !important;
+}
+
+/* Error messages */
+.error, .messagelist .error {
+ background-color: #f8d7da !important;
+ border-color: #f5c6cb !important;
+ color: #721c24 !important;
+}
+
+/* Improve table readability */
+#result_list tbody tr:nth-child(odd) {
+ background-color: #f9f9f9;
+}
+
+#result_list tbody tr:nth-child(even) {
+ background-color: #ffffff;
+}
+
+/* Better button styling */
+.button, input[type=submit], input[type=button], .submit-row input {
+ background: #417690 !important;
+ color: white !important;
+ border: none !important;
+ padding: 10px 15px !important;
+ border-radius: 4px !important;
+ cursor: pointer !important;
+}
+
+.button:hover, input[type=submit]:hover, input[type=button]:hover {
+ background: #305d75 !important;
+}
+
+/* Delete button styling */
+.deletelink, .deletelink-box a {
+ background: #dc3545 !important;
+}
+
+.deletelink:hover, .deletelink-box a:hover {
+ background: #c82333 !important;
+}
+
+/* Improve filter sidebar */
+#changelist-filter h2 {
+ background: #417690;
+ color: white;
+ padding: 8px 10px;
+ margin-bottom: 0;
+}
+
+#changelist-filter h3 {
+ font-weight: bold;
+ margin-top: 15px;
+ padding-bottom: 5px;
+ border-bottom: 1px solid #ddd;
+}
+
+/* Better pagination */
+.paginator {
+ font-size: 14px;
+ padding: 10px;
+ background: #f8f9fa;
+ border-radius: 4px;
+}
+
+.paginator a {
+ padding: 5px 10px;
+ margin: 0 2px;
+ background: white;
+ border: 1px solid #ddd;
+ border-radius: 3px;
+}
+
+.paginator a:hover {
+ background: #417690;
+ color: white;
+ text-decoration: none;
+}
+
+/* Responsive improvements */
+@media (max-width: 768px) {
+ #content-main {
+ padding: 10px;
+ }
+
+ .module table {
+ font-size: 12px;
+ }
+}
+
+/* Admin header improvements */
+#header {
+ background: #417690;
+ color: white;
+}
+
+#header a:link, #header a:visited {
+ color: white;
+}
+
+#branding h1 {
+ color: white;
+}
+
+/* Fieldset legend styling */
+fieldset.module h2 {
+ background: #417690;
+ color: white;
+ padding: 8px 10px;
+ border-radius: 4px 4px 0 0;
+}
+
+/* Inline forms */
+.inline-group {
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ margin-bottom: 20px;
+}
+
+.inline-group .tabular {
+ overflow-x: auto;
+}
+
+/* Help text styling */
+.help {
+ font-size: 12px;
+ color: #666;
+ display: block;
+ margin-top: 5px;
+}
+
+/* Dashboard widget styling */
+.dashboard-card {
+ background: white;
+ border: 1px solid #ddd;
+ border-radius: 8px;
+ padding: 20px;
+ margin: 10px 0;
+ 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 {
+ display: inline-block;
+ margin: 10px 20px 10px 0;
+}
+
+.metric-value {
+ font-size: 32px;
+ font-weight: bold;
+ color: #417690;
+ display: block;
+}
+
+.metric-label {
+ font-size: 12px;
+ color: #666;
+ display: block;
+ margin-top: 5px;
+}
+
+/* Alert styling */
+.alert {
+ padding: 15px;
+ margin: 10px 0;
+ border-radius: 4px;
+ border-left: 4px solid;
+}
+
+.alert-error {
+ background-color: #f8d7da;
+ border-left-color: #dc3545;
+ color: #721c24;
+}
+
+.alert-warning {
+ background-color: #fff3cd;
+ border-left-color: #ffc107;
+ color: #856404;
+}
+
+.alert-info {
+ background-color: #d1ecf1;
+ border-left-color: #17a2b8;
+ color: #0c5460;
+}
+
+.alert-success {
+ background-color: #d4edda;
+ border-left-color: #28a745;
+ color: #155724;
+}
diff --git a/backend/igny8_core/templates/admin/base_site.html b/backend/igny8_core/templates/admin/base_site.html
new file mode 100644
index 00000000..1446add4
--- /dev/null
+++ b/backend/igny8_core/templates/admin/base_site.html
@@ -0,0 +1,19 @@
+{% extends "admin/base.html" %}
+{% load static %}
+
+{% block title %}{{ title }} | IGNY8 Admin{% endblock %}
+
+{% block branding %}
+
+{% endblock %}
+
+{% block extrastyle %}
+ {{ block.super }}
+
+{% endblock %}
+
+{% block nav-global %}{% endblock %}