629 lines
20 KiB
Markdown
629 lines
20 KiB
Markdown
# 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
|