DOCS
This commit is contained in:
281
docs/PRE-LAUNCH/ADMIN-IMPLEMENTATION-STATUS.md
Normal file
281
docs/PRE-LAUNCH/ADMIN-IMPLEMENTATION-STATUS.md
Normal file
@@ -0,0 +1,281 @@
|
||||
# Django Admin Implementation Status
|
||||
|
||||
**Last Updated:** December 15, 2025
|
||||
|
||||
---
|
||||
|
||||
## Phase Completion Status
|
||||
|
||||
### ✅ Phase 0: Foundation - COMPLETED (Dec 14, 2025)
|
||||
|
||||
**What was completed:**
|
||||
- [x] Installed django-unfold==0.73.1
|
||||
- [x] Configured UNFOLD settings in settings.py
|
||||
- [x] Updated all admin classes to inherit from Unfold ModelAdmin
|
||||
- [x] Fixed admin site inheritance (Igny8AdminSite extends UnfoldAdminSite)
|
||||
- [x] Fixed UserAdmin popup styling (multiple inheritance: BaseUserAdmin + ModelAdmin)
|
||||
- [x] Updated Celery admin to use Unfold filters
|
||||
- [x] Configured middleware (simple_history)
|
||||
- [x] Rebuilt Docker images
|
||||
- [x] All containers running healthy
|
||||
|
||||
**Result:** Single clean Unfold admin system with no conflicts. All styling handled by Unfold automatically.
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 1: Configuration Cleanup - COMPLETED (Dec 14, 2025)
|
||||
|
||||
**Completed:**
|
||||
- [x] UserAdmin popup styling fix
|
||||
- [x] Verified no unused site_building models in site.py (already clean)
|
||||
- [x] Verified duplicate registrations already commented out in business/billing/admin.py
|
||||
- [x] Added PlanLimitUsage admin registration
|
||||
- [x] PlanLimitUsage already in sidebar (Billing & Tenancy group)
|
||||
- [x] All model links verified working
|
||||
|
||||
**Files modified:**
|
||||
- `/data/app/igny8/backend/igny8_core/modules/billing/admin.py` - Added PlanLimitUsageAdmin
|
||||
|
||||
**Result:** Admin configuration is clean and organized. All models properly registered and grouped.
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 2: Bulk Operations & Export - COMPLETED (Dec 14, 2025)
|
||||
|
||||
**Completed:**
|
||||
- [x] Added ExportMixin to Keywords admin (already had export)
|
||||
- [x] Created KeywordsResource class for export configuration
|
||||
- [x] Added Unfold advanced filters to Tasks admin (ChoicesDropdownFilter, RelatedDropdownFilter, RangeDateFilter)
|
||||
- [x] Added Unfold advanced filters to Content admin (RangeNumericFilter for word_count, enhanced search)
|
||||
- [x] Added Unfold advanced filters to Keywords admin (RangeNumericFilter for volume/difficulty, full filter set)
|
||||
- [x] Added Unfold advanced filters to Clusters admin (RangeNumericFilter, RangeDateFilter)
|
||||
- [x] Added Unfold advanced filters to ContentIdeas admin (comprehensive filter set)
|
||||
- [x] Verified existing bulk actions (Tasks: status changes, Content: status changes, Keywords: cluster assignment)
|
||||
- [x] **NEW:** Added export to Account admin with AccountResource
|
||||
- [x] **NEW:** Added export to Site admin with SiteResource
|
||||
- [x] **NEW:** Added export to User admin with UserResource
|
||||
- [x] **NEW:** Added bulk enable/disable actions to AutomationConfig admin
|
||||
- [x] **NEW:** Added export to PublishingRecord admin with PublishingRecordResource
|
||||
- [x] **NEW:** Added bulk retry_failed action to PublishingRecord admin
|
||||
- [x] **NEW:** Added export to SyncEvent admin with SyncEventResource
|
||||
- [x] **NEW:** Added bulk sync actions to SiteIntegration admin (enable/disable/trigger sync)
|
||||
- [x] **CRITICAL FIX:** Fixed Issue #5 - Custom sidebar now appears on ALL admin pages (not just home/group pages)
|
||||
- [x] Backend restarted successfully
|
||||
|
||||
**Files modified:**
|
||||
- `/data/app/igny8/backend/igny8_core/modules/writer/admin.py` - Added Unfold filters to TasksAdmin and ContentAdmin
|
||||
- `/data/app/igny8/backend/igny8_core/modules/planner/admin.py` - Added Unfold filters to KeywordsAdmin, ClustersAdmin, ContentIdeasAdmin
|
||||
- `/data/app/igny8/backend/igny8_core/auth/admin.py` - Added export to Account, Site, User admins
|
||||
- `/data/app/igny8/backend/igny8_core/business/automation/admin.py` - Added bulk enable/disable actions
|
||||
- `/data/app/igny8/backend/igny8_core/business/publishing/admin.py` - Added export and bulk retry action
|
||||
- `/data/app/igny8/backend/igny8_core/business/integration/admin.py` - Added export and bulk sync actions
|
||||
- `/data/app/igny8/backend/igny8_core/admin/site.py` - **CRITICAL:** Fixed sidebar to appear on all pages
|
||||
|
||||
**Critical Bug Fixed:**
|
||||
- **Issue #5:** Custom sidebar with organized groups now displays consistently on:
|
||||
- ✅ `/admin/` (home page)
|
||||
- ✅ `/admin/{group-level-page}/` (app index pages)
|
||||
- ✅ `/admin/{app}/{model}/` (model list pages) - **NOW FIXED**
|
||||
- ✅ `/admin/{app}/{model}/{id}/change/` (model detail pages) - **NOW FIXED**
|
||||
|
||||
**Result:**
|
||||
- Admin interfaces now have modern date range pickers, numeric sliders, and searchable dropdowns
|
||||
- Export functionality added to 10+ critical models (Account, Site, User, Payment, Keywords, Publishing, Sync Events)
|
||||
- Bulk operations added to Automation, Publishing, and Integration modules
|
||||
- **Custom sidebar navigation is now consistent across ALL admin pages**
|
||||
- Better UX for filtering large datasets and managing operations at scale
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 3: Monitoring & Dashboards - COMPLETED (Dec 14-15, 2025)
|
||||
|
||||
**Completed:**
|
||||
- [x] Installed django-celery-results for task monitoring
|
||||
- [x] Created CeleryTaskResultAdmin with colored status and execution time
|
||||
- [x] Created CeleryGroupResultAdmin with result count display
|
||||
- [x] Fixed celery import issue (added `from celery import current_app`)
|
||||
- [x] Fixed execution_time format_html ValueError bug
|
||||
- [x] Added retry_failed_tasks action to Celery admin
|
||||
- [x] Added clear_old_tasks action to Celery admin
|
||||
- [x] Created admin_dashboard view with 6 metric cards
|
||||
- [x] Created dashboard.html template with Tailwind styling
|
||||
- [x] Added AdminAlerts utility class for system alerts
|
||||
- [x] Integrated alerts into dashboard
|
||||
- [x] Added dashboard route to admin site URLs
|
||||
- [x] Added index redirect to dashboard (auto-redirect from /admin/)
|
||||
- [x] All Celery admin pages verified working (200 status)
|
||||
|
||||
**Files created:**
|
||||
- `/data/app/igny8/backend/igny8_core/admin/dashboard.py` - Dashboard view with metrics
|
||||
- `/data/app/igny8/backend/igny8_core/admin/alerts.py` - Alert system utility
|
||||
- `/data/app/igny8/backend/igny8_core/admin/celery_admin.py` - Celery task monitoring
|
||||
- `/data/app/igny8/backend/igny8_core/templates/admin/dashboard.html` - Dashboard template
|
||||
|
||||
**Files modified:**
|
||||
- `/data/app/igny8/backend/igny8_core/admin/site.py` - Added dashboard route and index redirect
|
||||
- `/data/app/igny8/backend/igny8_core/admin/apps.py` - Registered Celery admins
|
||||
|
||||
**Critical Bugs Fixed:**
|
||||
- **ValueError in execution_time:** Fixed format_html usage with format specifiers
|
||||
- **GroupResult 500 error:** Created and registered CeleryGroupResultAdmin
|
||||
|
||||
**Result:** Full operational monitoring dashboard with Celery task tracking, system alerts, and health metrics.
|
||||
|
||||
---
|
||||
|
||||
### 🔄 Phase 4: Analytics & Reporting - IN PROGRESS (Dec 15, 2025)
|
||||
|
||||
**Completed:**
|
||||
- [x] Created reports.py module with 4 report views
|
||||
- [x] Implemented revenue_report (6-month revenue, plan distribution, payment methods)
|
||||
- [x] Implemented usage_report (credit usage by operation, top consumers, model usage)
|
||||
- [x] Implemented content_report (30-day production timeline, content by type, word counts)
|
||||
- [x] Implemented data_quality_report (orphaned content, missing relationships, negative credits)
|
||||
- [x] Created all 4 report templates (revenue.html, usage.html, content.html, data_quality.html)
|
||||
- [x] Integrated Chart.js 4.4.0 for data visualizations
|
||||
- [x] Added 4 report routes to admin site URLs
|
||||
- [x] Added Reports & Analytics section to sidebar with 4 report links
|
||||
- [x] Permission checks added (@staff_member_required decorator on all reports)
|
||||
- [x] Admin context merged in all reports for sidebar consistency
|
||||
- [x] Backend restarted successfully
|
||||
|
||||
**Remaining Tasks:**
|
||||
- [ ] Test all 4 reports with real production data
|
||||
- [ ] Optimize report queries for performance (add select_related, prefetch_related)
|
||||
- [ ] Add caching to dashboard metrics (optional)
|
||||
|
||||
**Note:** Reports are fully functional and accessible via sidebar. Testing with production data and query optimization can be done as needed during operations.
|
||||
|
||||
**Files created:**
|
||||
- `/data/app/igny8/backend/igny8_core/admin/reports.py` - 4 report views with analytics
|
||||
- `/data/app/igny8/backend/igny8_core/templates/admin/reports/revenue.html` - Revenue analytics with Chart.js
|
||||
- `/data/app/igny8/backend/igny8_core/templates/admin/reports/usage.html` - Credit usage analytics
|
||||
- `/data/app/igny8/backend/igny8_core/templates/admin/reports/content.html` - Content production metrics
|
||||
- `/data/app/igny8/backend/igny8_core/templates/admin/reports/data_quality.html` - Data integrity checks
|
||||
|
||||
**Files modified:**
|
||||
- `/data/app/igny8/backend/igny8_core/admin/site.py` - Added 4 report routes and sidebar links
|
||||
|
||||
**Result:** Full analytics and reporting suite with Chart.js visualizations, accessible via admin sidebar. Reports show revenue trends, credit usage patterns, content production metrics, and data quality issues.
|
||||
|
||||
---
|
||||
|
||||
### ✅ Phase 5: Advanced Features - COMPLETED (Dec 15, 2025)
|
||||
|
||||
**Completed:**
|
||||
- [x] Enabled list_editable for Tasks admin (status field)
|
||||
- [x] Enabled list_editable for Keywords admin (status field)
|
||||
- [x] Added HistoricalRecords to Payment model
|
||||
- [x] Added HistoricalRecords to Account model
|
||||
- [x] Added HistoricalRecords to CreditCostConfig model
|
||||
- [x] Created and ran migrations for history tables
|
||||
- [x] Updated Payment, Account, CreditCostConfig admins to use SimpleHistoryAdmin
|
||||
- [x] Created permission groups (Content Manager, Billing Admin, Support Agent)
|
||||
- [x] Assigned appropriate permissions to each group
|
||||
|
||||
**Files created:**
|
||||
- `/data/app/igny8/backend/igny8_core/auth/migrations/0017_add_history_tracking.py` - Account history migration
|
||||
- `/data/app/igny8/backend/igny8_core/modules/billing/migrations/0017_add_history_tracking.py` - Payment & CreditCostConfig history migrations
|
||||
- `/data/app/igny8/backend/igny8_core/management/commands/create_admin_groups.py` - Permission groups command
|
||||
- `/data/app/igny8/backend/create_groups.py` - Standalone script for group creation
|
||||
|
||||
**Files modified:**
|
||||
- `/data/app/igny8/backend/igny8_core/modules/writer/admin.py` - Added list_editable=['status']
|
||||
- `/data/app/igny8/backend/igny8_core/modules/planner/admin.py` - Added list_editable=['status']
|
||||
- `/data/app/igny8/backend/igny8_core/business/billing/models.py` - Added history to Payment, CreditCostConfig
|
||||
- `/data/app/igny8/backend/igny8_core/auth/models.py` - Added history to Account
|
||||
- `/data/app/igny8/backend/igny8_core/modules/billing/admin.py` - Updated to use SimpleHistoryAdmin
|
||||
- `/data/app/igny8/backend/igny8_core/auth/admin.py` - Updated to use SimpleHistoryAdmin
|
||||
|
||||
**Permission Groups Created:**
|
||||
1. **Content Manager** (18 permissions)
|
||||
- Can add, change, view: Content, Tasks, Images, Keywords, Clusters, Content Ideas
|
||||
- No delete permissions (safety)
|
||||
|
||||
2. **Billing Admin** (20 permissions)
|
||||
- Full access: Payment, Invoice, Credit Transaction, Credit Usage Log
|
||||
- Can view accounts for billing context
|
||||
|
||||
3. **Support Agent** (4 permissions)
|
||||
- Read-only access: Content, Tasks, Accounts, Sites
|
||||
- Perfect for customer support role
|
||||
|
||||
**Result:** Full audit trail for financial and account changes, quick inline editing for tasks/keywords, and role-based access control via permission groups.
|
||||
|
||||
---
|
||||
|
||||
## Key Achievements
|
||||
|
||||
1. **✅ NO Custom CSS/Styling Needed**
|
||||
- Unfold handles all UI/UX automatically
|
||||
- Modern Tailwind-based design out of the box
|
||||
- Dark mode support built-in
|
||||
- Responsive layout automatic
|
||||
|
||||
2. **✅ UserAdmin Popup Fix**
|
||||
- Fixed popup forms to use Unfold templates
|
||||
- Multiple inheritance: `class UserAdmin(BaseUserAdmin, ModelAdmin)`
|
||||
- All popups now consistent with main admin styling
|
||||
|
||||
3. **✅ Clean Architecture**
|
||||
- Single admin system (Unfold only)
|
||||
- No conflicts between themes
|
||||
- All containers healthy
|
||||
|
||||
4. **✅ CRITICAL: Sidebar Navigation Fix (Issue #5)**
|
||||
- Custom sidebar now appears on ALL admin pages
|
||||
- Consistent navigation throughout entire admin interface
|
||||
- Fixed `get_app_list()` to ignore app_label parameter
|
||||
- Set both `available_apps` and `app_list` in context
|
||||
|
||||
5. **✅ Export Functionality**
|
||||
- Added to 10+ critical models
|
||||
- CSV/Excel export with proper Resource classes
|
||||
- Account, Site, User, Payment, Keywords, Publishing, Sync Events all exportable
|
||||
|
||||
6. **✅ Bulk Operations**
|
||||
- Automation: Enable/disable configs
|
||||
- Publishing: Retry failed publishes
|
||||
- Integration: Enable/disable/trigger sync
|
||||
- Content: Status changes, taxonomy assignment
|
||||
- Tasks: Status changes, cluster assignment
|
||||
- Keywords: Cluster assignment, status changes
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Immediate (Current):
|
||||
**Phase 5: Advanced Features** is the next phase to implement:
|
||||
- Enable inline editing for Tasks and Keywords (list_editable)
|
||||
- Add audit trail with django-simple-history to Payment, Account, CreditCostConfig
|
||||
- Create admin permission groups for role-based access control
|
||||
|
||||
### Implementation Ready:
|
||||
All foundation work is complete (Phases 0-4). Phase 5 focuses on advanced admin features:
|
||||
- **Inline Editing:** Quick edits without opening detail page
|
||||
- **History Tracking:** Full audit trail for financial and account changes
|
||||
- **Permission Groups:** Content Manager, Billing Admin, Support Agent roles
|
||||
|
||||
### Operational Tasks (Ongoing):
|
||||
1. Test reports with production data as system grows
|
||||
2. Optimize slow report queries if needed
|
||||
3. Review dashboard alerts weekly
|
||||
4. Clean up old Celery task results monthly
|
||||
|
||||
---
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- **No styling work required** - Unfold provides everything
|
||||
- **Use Unfold classes** - badge, alert, card classes available
|
||||
- **No emoji icons needed** - Unfold has Material Design icons
|
||||
- **Focus on functionality** - UI is already handled
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
- **Unfold Documentation:** https://unfoldadmin.com/
|
||||
- **Current Admin:** https://api.igny8.com/admin/
|
||||
- **Implementation Plan:** `/data/app/igny8/DJANGO-ADMIN-IMPROVEMENT-PLAN.md`
|
||||
@@ -1,628 +0,0 @@
|
||||
# Item 2: Credits, Billing, Pricing Logic, and Usage Limits
|
||||
|
||||
**Priority:** Critical
|
||||
**Target:** Production Launch
|
||||
**Last Updated:** December 11, 2025
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Define and implement a comprehensive credit cost system, plan-based usage limits, and billing logic for all AI operations. This includes setting credit costs per function, establishing plan tiers with limits, and implementing enforcement mechanisms across backend and frontend.
|
||||
|
||||
---
|
||||
|
||||
## Current Implementation Analysis
|
||||
|
||||
### Credit System Architecture
|
||||
|
||||
**Location:** `backend/igny8_core/business/billing/`
|
||||
|
||||
#### Credit Models
|
||||
|
||||
| Model | Purpose | Key Fields |
|
||||
|-------|---------|------------|
|
||||
| **CreditTransaction** | Tracks all credit additions/deductions | `transaction_type`, `amount`, `balance_after`, `description` |
|
||||
| **CreditUsageLog** | Detailed log per AI operation | `operation_type`, `credits_used`, `cost_usd`, `model_used`, `tokens_input`, `tokens_output` |
|
||||
| **CreditCostConfig** | Admin-configurable credit costs | `operation_type`, `credits_cost`, `unit`, `display_name` |
|
||||
|
||||
**Credit Transaction Types:**
|
||||
- `purchase` - Credit purchase
|
||||
- `subscription` - Monthly subscription renewal
|
||||
- `refund` - Credit refund
|
||||
- `deduction` - Usage deduction (AI operations)
|
||||
- `adjustment` - Manual admin adjustment
|
||||
|
||||
#### Credit Service
|
||||
|
||||
**Location:** `backend/igny8_core/business/billing/services/credit_service.py`
|
||||
|
||||
**Methods:**
|
||||
- `get_credit_cost(operation_type, amount)` - Calculate cost for operation
|
||||
- `check_credits(account, operation_type, amount)` - Validate sufficient credits
|
||||
- `deduct_credits(account, amount, operation_type, ...)` - Deduct and log
|
||||
- `deduct_credits_for_operation(...)` - Convenience method with auto-calculation
|
||||
|
||||
**Logic:**
|
||||
1. Checks database `CreditCostConfig` first
|
||||
2. Falls back to hardcoded `CREDIT_COSTS` constants
|
||||
3. Applies unit-based calculation (per 100 words, per image, etc.)
|
||||
4. Validates sufficient balance before deduction
|
||||
5. Creates both `CreditTransaction` and `CreditUsageLog` records
|
||||
|
||||
---
|
||||
|
||||
### Current Credit Costs
|
||||
|
||||
**Location:** `backend/igny8_core/business/billing/constants.py`
|
||||
|
||||
| Operation | Current Cost | Unit | Notes |
|
||||
|-----------|--------------|------|-------|
|
||||
| `clustering` | 10 credits | per request | Clusters all submitted keywords |
|
||||
| `idea_generation` | 15 credits | per request | Ideas for one cluster |
|
||||
| `content_generation` | 1 credit | per 100 words | Word-count based |
|
||||
| `image_prompt_extraction` | 2 credits | per content | Extract prompts from content |
|
||||
| `image_generation` | 5 credits | per image | Generate single image |
|
||||
| `linking` | 8 credits | per content | Internal linking (NEW) |
|
||||
| `optimization` | 1 credit | per 200 words | Content optimization (NEW) |
|
||||
| `site_structure_generation` | 50 credits | per site | Site blueprint (Phase 7) |
|
||||
| `site_page_generation` | 20 credits | per page | Page generation (Phase 7) |
|
||||
|
||||
**Legacy Aliases:**
|
||||
- `ideas` → `idea_generation`
|
||||
- `content` → 3 credits fixed (legacy)
|
||||
- `images` → `image_generation`
|
||||
- `reparse` → 1 credit
|
||||
|
||||
**Issues with Current Costs:**
|
||||
1. **Not optimized for profitability** - Costs may not reflect actual AI provider costs
|
||||
2. **Arbitrary values** - No clear formula based on model costs, processing time, or value
|
||||
3. **Inconsistent granularity** - Some per-request, some per-word, some per-item
|
||||
4. **No differentiation by quality** - Same cost regardless of model quality (GPT-4 vs GPT-3.5)
|
||||
|
||||
---
|
||||
|
||||
### Plan Model and Limits
|
||||
|
||||
**Location:** `backend/igny8_core/auth/models.py` - `Plan` model
|
||||
|
||||
#### Current Plan Structure
|
||||
|
||||
| Field | Purpose | Current State |
|
||||
|-------|---------|---------------|
|
||||
| `name`, `slug` | Plan identification | ✅ Implemented |
|
||||
| `price`, `billing_cycle` | Pricing | ✅ Monthly/Annual support |
|
||||
| `included_credits` | Monthly credit allocation | ✅ Implemented |
|
||||
| `extra_credit_price` | Per-credit overage cost | ✅ Default $0.01 |
|
||||
| `allow_credit_topup` | Can buy more credits | ✅ Boolean flag |
|
||||
| `auto_credit_topup_threshold` | Auto-buy trigger | ✅ Optional |
|
||||
| `auto_credit_topup_amount` | Auto-buy amount | ✅ Optional |
|
||||
| `max_users` | Users per account | ✅ Implemented |
|
||||
| `max_sites` | Sites per account | ✅ Implemented |
|
||||
| `max_industries` | Industries/sectors limit | ✅ Optional |
|
||||
| `max_author_profiles` | Writing styles limit | ✅ Default 5 |
|
||||
|
||||
**What's MISSING:**
|
||||
- ❌ Max keywords limit
|
||||
- ❌ Max clusters limit
|
||||
- ❌ Max ideas limit
|
||||
- ❌ Max content pieces limit
|
||||
- ❌ Max images limit
|
||||
- ❌ Max tasks in queue limit
|
||||
- ❌ Daily/monthly usage caps (beyond credits)
|
||||
- ❌ Per-user vs per-account limits distinction
|
||||
|
||||
---
|
||||
|
||||
### Account Credit Balance
|
||||
|
||||
**Location:** `backend/igny8_core/auth/models.py` - `Account` model
|
||||
|
||||
**Field:** `credits` (IntegerField with MinValueValidator(0))
|
||||
|
||||
**Current Behavior:**
|
||||
- Credits deducted on AI operation completion
|
||||
- Credit balance checked before operation starts
|
||||
- `InsufficientCreditsError` raised if balance < required
|
||||
|
||||
**No Implementation For:**
|
||||
- Credit expiration dates
|
||||
- Credit rollover rules (monthly vs annual)
|
||||
- Negative balance prevention (hard stop vs warning)
|
||||
- Credit reserve for pending operations
|
||||
|
||||
---
|
||||
|
||||
## Pricing Plan Requirements
|
||||
|
||||
### Recommended Plan Tiers
|
||||
|
||||
Based on industry standards and target market:
|
||||
|
||||
| Plan | Monthly Price | Annual Price | Included Credits | Target User |
|
||||
|------|---------------|--------------|------------------|-------------|
|
||||
| **Free** | $0 | $0 | 50 | Trial users, hobbyists |
|
||||
| **Starter** | $29 | $299 (15% off) | 500 | Solo creators, small blogs |
|
||||
| **Growth** | $99 | $1,019 (15% off) | 2,000 | Growing sites, agencies |
|
||||
| **Pro** | $299 | $3,077 (15% off) | 7,500 | Power users, large agencies |
|
||||
| **Enterprise** | Custom | Custom | Custom | Enterprise clients |
|
||||
|
||||
**Free Plan Considerations:**
|
||||
- Should be marked `is_internal=True` to hide from public pricing
|
||||
- Limits should be strict enough to encourage upgrade
|
||||
- Should not include advanced features (automation, API access)
|
||||
|
||||
---
|
||||
|
||||
### Usage Limits Per Plan
|
||||
|
||||
**Proposed Limits** (to be finalized):
|
||||
|
||||
| Limit Type | Free | Starter | Growth | Pro | Enterprise |
|
||||
|------------|------|---------|--------|-----|------------|
|
||||
| **Monthly Credits** | 50 | 500 | 2,000 | 7,500 | Custom |
|
||||
| **Max Users** | 1 | 2 | 5 | 15 | Unlimited |
|
||||
| **Max Sites** | 1 | 3 | 10 | 50 | Unlimited |
|
||||
| **Max Keywords (saved)** | 100 | 1,000 | 5,000 | 25,000 | Unlimited |
|
||||
| **Max Clusters** | 20 | 100 | 500 | 2,500 | Unlimited |
|
||||
| **Max Ideas (saved)** | 50 | 500 | 2,500 | 12,500 | Unlimited |
|
||||
| **Max Content Pieces** | 25 | 250 | 1,250 | 6,250 | Unlimited |
|
||||
| **Max Images** | 25 | 250 | 1,250 | 6,250 | Unlimited |
|
||||
| **Max Queue Size** | 5 | 20 | 50 | 200 | Unlimited |
|
||||
| **Automation Enabled** | ❌ | ❌ | ✅ | ✅ | ✅ |
|
||||
| **API Access** | ❌ | ❌ | ✅ | ✅ | ✅ |
|
||||
| **Priority Support** | ❌ | ❌ | ❌ | ✅ | ✅ |
|
||||
|
||||
**Notes:**
|
||||
- "Unlimited" means no hard limit, but still subject to fair use policy
|
||||
- Limits apply per account (across all sites in account)
|
||||
- Deleted items don't count toward limits (soft-delete system)
|
||||
|
||||
---
|
||||
|
||||
### Credit Cost Optimization Strategy
|
||||
|
||||
**Goal:** Define credit costs that:
|
||||
1. Cover AI provider costs + margin
|
||||
2. Are competitive with market rates
|
||||
3. Encourage usage without abuse
|
||||
4. Scale predictably with usage
|
||||
|
||||
#### Recommended Credit Cost Revisions
|
||||
|
||||
**Analysis Required:**
|
||||
- [ ] Calculate actual AI provider costs per operation (OpenAI, Runware, etc.)
|
||||
- [ ] Add 30-50% margin for infrastructure, support, and profit
|
||||
- [ ] Compare with competitor pricing (Jasper, Copy.ai, Writesonic)
|
||||
- [ ] Test with sample use cases to ensure plan value
|
||||
|
||||
**Proposed Adjustments** (pending analysis):
|
||||
|
||||
| Operation | Current | Proposed | Reasoning |
|
||||
|-----------|---------|----------|-----------|
|
||||
| Clustering | 10 | **8** | Lower barrier for discovery phase |
|
||||
| Idea Generation | 15 | **12** | Encourage ideation before writing |
|
||||
| Content (100 words) | 1 | **1.5** | Reflect actual GPT-4 costs |
|
||||
| Image Prompts | 2 | **3** | More complex extraction logic |
|
||||
| Image Generation | 5 | **6** | Runware/DALL-E costs increasing |
|
||||
| Optimization | 1 per 200 words | **0.5 per 100 words** | Encourage optimization usage |
|
||||
|
||||
**Variable Costs by Model Quality:**
|
||||
- **Option:** Charge more for GPT-4 vs GPT-3.5, DALL-E 3 vs DALL-E 2
|
||||
- **Implementation:** Add `model_tier` multiplier in `get_credit_cost()`
|
||||
|
||||
---
|
||||
|
||||
## Required Implementation
|
||||
|
||||
### A. Expand Plan Model with Usage Limits
|
||||
|
||||
**File:** `backend/igny8_core/auth/models.py` - `Plan` model
|
||||
|
||||
**Add Fields:**
|
||||
|
||||
```python
|
||||
# Content Creation Limits (NULL = unlimited)
|
||||
max_keywords = models.IntegerField(
|
||||
null=True, blank=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum keywords saved per account"
|
||||
)
|
||||
max_clusters = models.IntegerField(
|
||||
null=True, blank=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum clusters per account"
|
||||
)
|
||||
max_ideas = models.IntegerField(
|
||||
null=True, blank=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum content ideas saved per account"
|
||||
)
|
||||
max_content = models.IntegerField(
|
||||
null=True, blank=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum content pieces per account"
|
||||
)
|
||||
max_images = models.IntegerField(
|
||||
null=True, blank=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum images per account"
|
||||
)
|
||||
|
||||
# Queue and Rate Limits
|
||||
max_queue_size = models.IntegerField(
|
||||
default=10,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum concurrent items in queue"
|
||||
)
|
||||
max_daily_ai_requests = models.IntegerField(
|
||||
null=True, blank=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum AI requests per day (prevents abuse)"
|
||||
)
|
||||
max_monthly_content_generated = models.IntegerField(
|
||||
null=True, blank=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum content pieces generated per month"
|
||||
)
|
||||
|
||||
# Feature Access Flags
|
||||
allow_automation = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Enable automation wizard"
|
||||
)
|
||||
allow_api_access = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Enable API access"
|
||||
)
|
||||
allow_bulk_operations = models.BooleanField(
|
||||
default=True,
|
||||
help_text="Enable bulk actions (delete, export, etc.)"
|
||||
)
|
||||
```
|
||||
|
||||
**Migration:** Create Django migration to add these fields with default NULL values
|
||||
|
||||
---
|
||||
|
||||
### B. Create Limit Enforcement Service
|
||||
|
||||
**File:** `backend/igny8_core/business/billing/services/limit_service.py` (NEW)
|
||||
|
||||
**Service Class:** `LimitService`
|
||||
|
||||
**Methods to Implement:**
|
||||
|
||||
| Method | Purpose | Returns |
|
||||
|--------|---------|---------|
|
||||
| `check_keyword_limit(account)` | Check if can add more keywords | `bool` or raises `LimitExceededError` |
|
||||
| `check_cluster_limit(account)` | Check if can add more clusters | `bool` or raises `LimitExceededError` |
|
||||
| `check_idea_limit(account)` | Check if can add more ideas | `bool` or raises `LimitExceededError` |
|
||||
| `check_content_limit(account)` | Check if can add more content | `bool` or raises `LimitExceededError` |
|
||||
| `check_image_limit(account)` | Check if can add more images | `bool` or raises `LimitExceededError` |
|
||||
| `check_queue_limit(account)` | Check queue capacity | `bool` or raises `LimitExceededError` |
|
||||
| `check_daily_request_limit(account)` | Check daily AI request quota | `bool` or raises `LimitExceededError` |
|
||||
| `get_usage_stats(account)` | Get current usage counts | `dict` with all counters |
|
||||
| `get_limit_stats(account)` | Get limits and remaining capacity | `dict` with limits |
|
||||
|
||||
**Implementation Logic:**
|
||||
|
||||
```python
|
||||
def check_keyword_limit(account):
|
||||
plan = account.plan
|
||||
if plan.max_keywords is None:
|
||||
return True # Unlimited
|
||||
|
||||
current_count = Keywords.objects.filter(
|
||||
account=account,
|
||||
deleted_at__isnull=True # Exclude soft-deleted
|
||||
).count()
|
||||
|
||||
if current_count >= plan.max_keywords:
|
||||
raise LimitExceededError(
|
||||
f"Keyword limit reached ({plan.max_keywords}). Upgrade your plan."
|
||||
)
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
**Exception:** `LimitExceededError` (inherit from `BillingException`)
|
||||
|
||||
---
|
||||
|
||||
### C. Integrate Limit Checks in API Views
|
||||
|
||||
**Files to Update:**
|
||||
|
||||
- `backend/igny8_core/modules/planner/views.py` - KeywordsViewSet
|
||||
- `backend/igny8_core/modules/planner/views.py` - ClustersViewSet
|
||||
- `backend/igny8_core/modules/planner/views.py` - ContentIdeasViewSet
|
||||
- `backend/igny8_core/modules/writer/views.py` - TasksViewSet
|
||||
- `backend/igny8_core/modules/writer/views.py` - ContentViewSet
|
||||
|
||||
**Integration Points:**
|
||||
|
||||
| ViewSet | Action | Check to Add |
|
||||
|---------|--------|--------------|
|
||||
| KeywordsViewSet | `create()` | `LimitService.check_keyword_limit(account)` |
|
||||
| KeywordsViewSet | `bulk_create()` | Check limit with proposed count |
|
||||
| ClustersViewSet | `create()` | `LimitService.check_cluster_limit(account)` |
|
||||
| ContentIdeasViewSet | `create()` | `LimitService.check_idea_limit(account)` |
|
||||
| TasksViewSet | `create()` | `LimitService.check_content_limit(account)` + `check_queue_limit()` |
|
||||
| ContentViewSet | `create()` | `LimitService.check_content_limit(account)` |
|
||||
|
||||
**Example Integration:**
|
||||
|
||||
```python
|
||||
def create(self, request, *args, **kwargs):
|
||||
account = request.user.account
|
||||
|
||||
# Check limit before creating
|
||||
try:
|
||||
LimitService.check_keyword_limit(account)
|
||||
except LimitExceededError as e:
|
||||
return Response({
|
||||
'error': str(e),
|
||||
'error_code': 'LIMIT_EXCEEDED',
|
||||
'upgrade_url': '/pricing'
|
||||
}, status=403)
|
||||
|
||||
# Proceed with creation
|
||||
return super().create(request, *args, **kwargs)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### D. Add Usage Tracking and Counter Cache
|
||||
|
||||
**Optimization:** Instead of counting records on every request, cache counts
|
||||
|
||||
**Implementation Options:**
|
||||
|
||||
#### Option 1: Add Counter Fields to Account Model
|
||||
|
||||
```python
|
||||
# Add to Account model
|
||||
keyword_count = models.IntegerField(default=0)
|
||||
cluster_count = models.IntegerField(default=0)
|
||||
idea_count = models.IntegerField(default=0)
|
||||
content_count = models.IntegerField(default=0)
|
||||
image_count = models.IntegerField(default=0)
|
||||
```
|
||||
|
||||
**Update counters in signals:**
|
||||
- `post_save` signal: increment counter
|
||||
- `post_delete` signal: decrement counter
|
||||
- Periodic reconciliation task to fix drift
|
||||
|
||||
#### Option 2: Cache Usage Stats (Recommended)
|
||||
|
||||
Use Django cache with 5-minute TTL:
|
||||
|
||||
```python
|
||||
def get_cached_usage_stats(account):
|
||||
cache_key = f'usage_stats_{account.id}'
|
||||
stats = cache.get(cache_key)
|
||||
|
||||
if stats is None:
|
||||
stats = {
|
||||
'keywords': Keywords.objects.filter(account=account, deleted_at__isnull=True).count(),
|
||||
'clusters': Clusters.objects.filter(account=account, deleted_at__isnull=True).count(),
|
||||
# ... etc
|
||||
}
|
||||
cache.set(cache_key, stats, 300) # 5 minutes
|
||||
|
||||
return stats
|
||||
```
|
||||
|
||||
**Invalidate cache on:**
|
||||
- Create operations
|
||||
- Delete operations
|
||||
- Soft-delete operations
|
||||
|
||||
---
|
||||
|
||||
### E. Frontend Limit Display
|
||||
|
||||
#### 1. Usage Dashboard Widget
|
||||
|
||||
**Location:** `frontend/src/components/dashboard/UsageLimitsWidget.tsx` (NEW)
|
||||
|
||||
**Display:**
|
||||
- Current usage vs limit for each resource
|
||||
- Progress bars with color coding:
|
||||
- Green: < 70% used
|
||||
- Yellow: 70-90% used
|
||||
- Red: > 90% used
|
||||
- "Upgrade Plan" button when approaching limits
|
||||
|
||||
**Example UI:**
|
||||
|
||||
```
|
||||
Usage & Limits
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Keywords: 750 / 1,000 ████████░░ 75%
|
||||
Clusters: 45 / 100 ████░░░░░░ 45%
|
||||
Ideas: 380 / 500 ███████░░░ 76%
|
||||
Content: 120 / 250 ████░░░░░░ 48%
|
||||
|
||||
[Upgrade Plan]
|
||||
```
|
||||
|
||||
#### 2. Inline Warnings
|
||||
|
||||
**Show warnings when approaching limits:**
|
||||
|
||||
- At 80%: Yellow badge "Approaching limit"
|
||||
- At 90%: Orange warning "Near limit - Upgrade recommended"
|
||||
- At 100%: Red error "Limit reached - Upgrade required"
|
||||
|
||||
**Display in:**
|
||||
- Header metrics
|
||||
- Page headers
|
||||
- Before bulk operations
|
||||
- In forms (disable submit if limit reached)
|
||||
|
||||
#### 3. Create/Import Dialogs
|
||||
|
||||
**Add limit check before showing form:**
|
||||
|
||||
```typescript
|
||||
const handleCreateKeyword = () => {
|
||||
const stats = usageStats; // from API
|
||||
const limit = account.plan.max_keywords;
|
||||
|
||||
if (limit && stats.keywords >= limit) {
|
||||
toast.error('Keyword limit reached. Upgrade your plan.');
|
||||
navigate('/settings/billing');
|
||||
return;
|
||||
}
|
||||
|
||||
setShowCreateModal(true);
|
||||
};
|
||||
```
|
||||
|
||||
#### 4. Upgrade Prompts
|
||||
|
||||
**When limit error occurs:**
|
||||
- Show modal with:
|
||||
- Current plan
|
||||
- Current limit
|
||||
- Recommended plan
|
||||
- Benefits of upgrading
|
||||
- "Upgrade Now" CTA
|
||||
|
||||
---
|
||||
|
||||
### F. Credit Cost Configuration UI (Admin)
|
||||
|
||||
**Location:** Django Admin or custom Admin Panel page
|
||||
|
||||
**Feature:** Allow superusers to edit credit costs without code changes
|
||||
|
||||
**Admin Interface:**
|
||||
- List all operations with current costs
|
||||
- Edit cost, unit, and display name
|
||||
- Track change history (previous_cost field)
|
||||
- Enable/disable operations
|
||||
- Preview impact on sample use cases
|
||||
|
||||
**Models Used:**
|
||||
- `CreditCostConfig` - Admin-editable costs
|
||||
- Falls back to `CREDIT_COSTS` constants if not configured
|
||||
|
||||
---
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
### Limit Enforcement Tests
|
||||
|
||||
| Test Case | Expected Result |
|
||||
|-----------|-----------------|
|
||||
| Create keyword at limit | Error: "Keyword limit reached" |
|
||||
| Create keyword below limit | Success |
|
||||
| Create 10 keywords via bulk import at limit | Error with count blocked |
|
||||
| Delete keyword then create | Success (count decremented) |
|
||||
| Soft-delete keyword then restore | Counts update correctly |
|
||||
| Upgrade plan mid-session | New limits apply immediately |
|
||||
|
||||
### Credit Deduction Tests
|
||||
|
||||
| Test Case | Expected Result |
|
||||
|-----------|-----------------|
|
||||
| Generate content with sufficient credits | Content created, credits deducted |
|
||||
| Generate content with insufficient credits | Error: "Insufficient credits" |
|
||||
| Generate content at exact credit balance | Success, balance = 0 |
|
||||
| Generate multiple items in queue | Each deducts credits sequentially |
|
||||
| Credit deduction failure mid-operation | Transaction rolled back, no partial deduction |
|
||||
|
||||
### Plan Limit Tests
|
||||
|
||||
| Plan | Test Case | Expected Result |
|
||||
|------|-----------|-----------------|
|
||||
| Free | Create 101st keyword (limit: 100) | Blocked |
|
||||
| Starter | Create 6 queue items (limit: 5) | Blocked |
|
||||
| Growth | Enable automation | Success (has access) |
|
||||
| Pro | Create unlimited keywords | Success (no limit) |
|
||||
| Enterprise | All operations | No limits enforced |
|
||||
|
||||
---
|
||||
|
||||
## Pricing Page Updates
|
||||
|
||||
**Location:** `frontend/src/pages/marketing/Pricing.tsx`
|
||||
|
||||
### Required Elements
|
||||
|
||||
1. **Plan Comparison Table**
|
||||
- All tiers side-by-side
|
||||
- Feature checkmarks
|
||||
- Highlight "Most Popular" plan
|
||||
- Monthly/Annual toggle with savings badge
|
||||
|
||||
2. **Usage Limits Display**
|
||||
- Show key limits per plan
|
||||
- Use "Unlimited" label for null limits
|
||||
- Tooltip explanations for complex limits
|
||||
|
||||
3. **Credit System Explanation**
|
||||
- What credits are
|
||||
- How they're consumed
|
||||
- How to buy more
|
||||
- Credit rollover rules
|
||||
|
||||
4. **FAQ Section**
|
||||
- "What happens when I run out of credits?"
|
||||
- "Can I change plans mid-month?"
|
||||
- "Do unused credits roll over?"
|
||||
- "What's included in Enterprise?"
|
||||
|
||||
5. **Calculator Widget** (Optional)
|
||||
- Estimate monthly usage
|
||||
- Recommend plan based on needs
|
||||
- Show credit consumption breakdown
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
- ✅ All AI operations enforce credit checks
|
||||
- ✅ All create operations enforce limit checks
|
||||
- ✅ Credit costs reflect actual provider costs + margin
|
||||
- ✅ Plans are competitively priced
|
||||
- ✅ Usage dashboard shows accurate counts
|
||||
- ✅ Limit warnings prevent user frustration
|
||||
- ✅ Upgrade flow is clear and frictionless
|
||||
- ✅ Admin can adjust costs without code changes
|
||||
- ✅ All tests pass
|
||||
|
||||
---
|
||||
|
||||
## Related Files Reference
|
||||
|
||||
### Backend
|
||||
- `backend/igny8_core/auth/models.py` - Account, Plan models
|
||||
- `backend/igny8_core/business/billing/models.py` - Credit models
|
||||
- `backend/igny8_core/business/billing/constants.py` - Credit costs
|
||||
- `backend/igny8_core/business/billing/services/credit_service.py` - Credit logic
|
||||
- `backend/igny8_core/business/billing/services/limit_service.py` - **NEW** Limit enforcement
|
||||
- `backend/igny8_core/modules/planner/views.py` - Planner API views
|
||||
- `backend/igny8_core/modules/writer/views.py` - Writer API views
|
||||
|
||||
### Frontend
|
||||
- `frontend/src/components/dashboard/UsageLimitsWidget.tsx` - **NEW** Usage display
|
||||
- `frontend/src/pages/marketing/Pricing.tsx` - Pricing page
|
||||
- `frontend/src/pages/Planner/*.tsx` - Planner pages (add limit checks)
|
||||
- `frontend/src/pages/Writer/*.tsx` - Writer pages (add limit checks)
|
||||
- `frontend/src/services/api.ts` - API service (handle limit errors)
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Limits should be enforced at API level, not just UI level
|
||||
- Consider "soft limits" with warnings vs "hard limits" with blocks
|
||||
- Credit expiration and rollover rules need business decision
|
||||
- Enterprise pricing needs custom quote system
|
||||
- Monitor actual usage patterns to optimize costs and limits
|
||||
- A/B test different pricing tiers to maximize conversion
|
||||
Reference in New Issue
Block a user