# Plan Limits Implementation Checklist **Version:** v1.1.0 (Minor version - new feature) **Started:** December 12, 2025 **Status:** In Progress --- ## 📋 Overview Implementing comprehensive plan limit system to enforce pricing tier limits for: - Hard limits (persistent): sites, users, keywords, clusters - Monthly limits (reset on billing cycle): content ideas, words, images, prompts --- ## Phase 1: Backend Setup ✅ / ❌ ### 1.1 Plan Model Updates - [ ] Add `max_keywords` field to Plan model - [ ] Add `max_clusters` field to Plan model - [ ] Add `max_content_ideas` field to Plan model - [ ] Add `max_content_words` field to Plan model - [ ] Add `max_images_basic` field to Plan model - [ ] Add `max_images_premium` field to Plan model - [ ] Add `max_image_prompts` field to Plan model - [ ] Add help text and validators for all fields - [ ] Update `__str__` method if needed **File:** `backend/igny8_core/auth/models.py` ### 1.2 PlanLimitUsage Model Creation - [ ] Create new `PlanLimitUsage` model - [ ] Add fields: account, limit_type, amount_used, period_start, period_end - [ ] Add Meta class with db_table, indexes, unique_together - [ ] Add `__str__` method - [ ] Add helper methods: `is_current_period()`, `remaining_allowance()` **File:** `backend/igny8_core/business/billing/models.py` ### 1.3 Database Migration - [ ] Run `makemigrations` command - [ ] Review generated migration - [ ] Test migration with `migrate --plan` - [ ] Run migration `migrate` - [ ] Verify schema in database **Command:** `python manage.py makemigrations && python manage.py migrate` ### 1.4 Data Seeding - [ ] Create data migration for existing plans - [ ] Populate limit fields with default values (Starter: 2/1/100K, Growth: 5/3/300K, Scale: Unlimited/5/500K) - [ ] Create initial PlanLimitUsage records for existing accounts - [ ] Calculate current usage from existing data **File:** `backend/igny8_core/business/billing/migrations/00XX_seed_plan_limits.py` ### 1.5 Word Counter Utility - [ ] Create `word_counter.py` utility - [ ] Implement `calculate_word_count(html_content)` function - [ ] Strip HTML tags using BeautifulSoup or regex - [ ] Handle edge cases (empty content, None, malformed HTML) - [ ] Add unit tests **File:** `backend/igny8_core/utils/word_counter.py` ### 1.6 Content Model Auto-Calculation - [ ] Update Content model `save()` method - [ ] Auto-calculate `word_count` when `content_html` changes - [ ] Use `word_counter.calculate_word_count()` - [ ] Test with sample content **File:** `backend/igny8_core/business/content/models.py` ### 1.7 LimitService Creation - [ ] Create `limit_service.py` - [ ] Implement `check_hard_limit(account, limit_type)` - sites, users, keywords, clusters - [ ] Implement `check_monthly_limit(account, limit_type, amount)` - ideas, words, images, prompts - [ ] Implement `increment_usage(account, limit_type, amount, metadata)` - [ ] Implement `get_usage_summary(account)` - current usage stats - [ ] Implement `get_current_period(account)` - get billing period - [ ] Create custom exceptions: `HardLimitExceededError`, `MonthlyLimitExceededError` - [ ] Add logging for all operations - [ ] Add unit tests **File:** `backend/igny8_core/business/billing/services/limit_service.py` ### 1.8 Update PlanSerializer - [ ] Add all new limit fields to `PlanSerializer.Meta.fields` - [ ] Test serialization - [ ] Verify API response includes new fields **File:** `backend/igny8_core/auth/serializers.py` ### 1.9 Create LimitUsageSerializer - [ ] Create `PlanLimitUsageSerializer` - [ ] Include all fields - [ ] Add computed fields: remaining, percentage_used **File:** `backend/igny8_core/business/billing/serializers.py` --- ## Phase 2: Backend Enforcement ✅ / ❌ ### 2.1 Hard Limit Enforcement - Sites - [ ] Update `SiteViewSet.create()` to check `max_sites` - [ ] Use `LimitService.check_hard_limit(account, 'sites')` - [ ] Return proper error message if limit exceeded - [ ] Test with different plan limits **File:** `backend/igny8_core/auth/views.py` ### 2.2 Hard Limit Enforcement - Users - [ ] Update user invitation logic to check `max_users` - [ ] Use `LimitService.check_hard_limit(account, 'users')` - [ ] Return proper error message if limit exceeded **File:** `backend/igny8_core/auth/views.py` (UserViewSet or invitation endpoint) ### 2.3 Hard Limit Enforcement - Keywords - [ ] Update keyword creation/import to check `max_keywords` - [ ] Check before bulk import - [ ] Check before individual creation - [ ] Use `LimitService.check_hard_limit(account, 'keywords')` **File:** `backend/igny8_core/business/planning/views.py` ### 2.4 Hard Limit Enforcement - Clusters - [ ] Update clustering service to check `max_clusters` - [ ] Check before AI clustering operation - [ ] Use `LimitService.check_hard_limit(account, 'clusters')` **File:** `backend/igny8_core/business/planning/services/clustering_service.py` ### 2.5 Monthly Limit Enforcement - Content Ideas - [ ] Update idea generation service - [ ] Check `max_content_ideas` before generation - [ ] Increment usage after successful generation - [ ] Use `LimitService.check_monthly_limit()` and `increment_usage()` **File:** `backend/igny8_core/business/planning/services/idea_service.py` or similar ### 2.6 Monthly Limit Enforcement - Content Words - [ ] Update content generation service - [ ] Check `max_content_words` before generation - [ ] Use `Content.word_count` for actual usage - [ ] Increment usage after content created - [ ] Sum word counts for batch operations **File:** `backend/igny8_core/business/content/services/content_generation_service.py` ### 2.7 Monthly Limit Enforcement - Images - [ ] Update image generation service - [ ] Check `max_images_basic` or `max_images_premium` based on model - [ ] Increment usage after image created - [ ] Track basic vs premium separately **File:** `backend/igny8_core/business/content/services/image_service.py` or similar ### 2.8 Monthly Limit Enforcement - Image Prompts - [ ] Update image prompt extraction - [ ] Check `max_image_prompts` before extraction - [ ] Increment usage after prompts extracted **File:** `backend/igny8_core/business/content/services/` (wherever prompts are extracted) ### 2.9 Automation Pipeline Integration - [ ] Update automation to check limits before each stage - [ ] Show limit warnings in pre-run estimation - [ ] Stop automation if limit would be exceeded - [ ] Log limit checks in activity log **File:** `backend/igny8_core/business/automation/services/` --- ## Phase 3: Monthly Reset Task ✅ / ❌ ### 3.1 Celery Task Creation - [ ] Create `reset_monthly_plan_limits()` task - [ ] Find accounts with billing period ending today - [ ] Reset PlanLimitUsage records - [ ] Create new records for new period - [ ] Log reset operations - [ ] Handle errors gracefully **File:** `backend/igny8_core/tasks/billing.py` ### 3.2 Celery Beat Schedule - [ ] Add task to `CELERY_BEAT_SCHEDULE` - [ ] Set to run daily at midnight UTC - [ ] Test task execution **File:** `backend/igny8_core/celery.py` ### 3.3 Manual Reset Capability - [ ] Create admin action to manually reset limits - [ ] Add to `PlanLimitUsageAdmin` - [ ] Test manual reset **File:** `backend/igny8_core/business/billing/admin.py` --- ## Phase 4: API Endpoints ✅ / ❌ ### 4.1 Limits Usage Endpoint - [ ] Create `/api/v1/billing/limits/usage/` endpoint - [ ] Return current usage for all limit types - [ ] Return remaining allowance - [ ] Return days until reset - [ ] Include plan limits for reference - [ ] Test endpoint **File:** `backend/igny8_core/business/billing/views.py` ### 4.2 Limits History Endpoint (Optional) - [ ] Create `/api/v1/billing/limits/history/` endpoint - [ ] Return historical usage data - [ ] Support date range filtering - [ ] Test endpoint **File:** `backend/igny8_core/business/billing/views.py` --- ## Phase 5: Frontend Updates ✅ / ❌ ### 5.1 Update Plan Interface - [ ] Add limit fields to Plan interface in `billing.api.ts` - [ ] Add limit fields to Plan interface in `Settings/Plans.tsx` - [ ] Add limit fields to Plan interface in `SignUpFormUnified.tsx` - [ ] Add limit fields to Plan interface in `AuthPages/SignUp.tsx` - [ ] Ensure consistency across all 4 locations **Files:** Multiple interface definitions ### 5.2 Create PlanLimitsWidget Component - [ ] Create `PlanLimitsWidget.tsx` component - [ ] Display hard limits (Sites, Users, Keywords, Clusters) with counts - [ ] Display monthly limits with progress bars - [ ] Show days until reset - [ ] Fetch from `/api/v1/billing/limits/usage/` - [ ] Add refresh capability - [ ] Style with existing design system **File:** `frontend/src/components/dashboard/PlanLimitsWidget.tsx` ### 5.3 Update Dashboard - [ ] Add `PlanLimitsWidget` to dashboard - [ ] Position alongside CreditBalanceWidget - [ ] Test responsive layout **File:** `frontend/src/pages/Dashboard/Dashboard.tsx` or similar ### 5.4 Update Settings/Plans Page - [ ] Display all limit fields in plan cards - [ ] Format numbers (1,000 / 100K / Unlimited) - [ ] Update `extractFeatures()` function - [ ] Test plan display **File:** `frontend/src/pages/Settings/Plans.tsx` ### 5.5 Update Usage Page - [ ] Add limits section to Usage page - [ ] Display current usage vs limits - [ ] Show limit types (hard vs monthly) - [ ] Add progress bars for monthly limits - [ ] Test with real data **File:** `frontend/src/pages/Billing/Usage.tsx` ### 5.6 Create Limit Exceeded Modal - [ ] Create `LimitExceededModal.tsx` component - [ ] Show when limit is reached - [ ] Display current usage and limit - [ ] Show upgrade options - [ ] Link to billing page - [ ] Style with existing modal pattern **File:** `frontend/src/components/billing/LimitExceededModal.tsx` ### 5.7 Add Limit Guards - [ ] Check limits before operations (optional - server-side is primary) - [ ] Show limit exceeded modal on API error - [ ] Handle `HardLimitExceededError` and `MonthlyLimitExceededError` - [ ] Display user-friendly messages **Files:** Various page components --- ## Phase 6: Admin & Testing ✅ / ❌ ### 6.1 Django Admin for PlanLimitUsage - [ ] Create `PlanLimitUsageAdmin` class - [ ] Add list display fields - [ ] Add filters (account, limit_type, period) - [ ] Add search fields - [ ] Add readonly fields (created_at, updated_at) - [ ] Add custom actions (reset, export) - [ ] Register admin **File:** `backend/igny8_core/business/billing/admin.py` ### 6.2 Update Plan Admin - [ ] Add new limit fields to `PlanAdmin` - [ ] Group fields logically (Hard Limits, Monthly Limits) - [ ] Add inline for related limit usage (optional) - [ ] Test admin interface **File:** `backend/igny8_core/auth/admin.py` ### 6.3 Backend Testing - [ ] Test hard limit checks - [ ] Test monthly limit checks - [ ] Test limit increment - [ ] Test monthly reset - [ ] Test word count calculation - [ ] Test API endpoints - [ ] Test error handling ### 6.4 Frontend Testing - [ ] Test plan display with limits - [ ] Test limits widget - [ ] Test usage page - [ ] Test limit exceeded modal - [ ] Test responsive design - [ ] Test with different plan tiers ### 6.5 Integration Testing - [ ] Test complete workflow: create content → check limits → increment usage - [ ] Test monthly reset → verify limits reset - [ ] Test upgrade plan → verify new limits apply - [ ] Test limit exceeded → verify operation blocked - [ ] Test across different accounts and sites --- ## Phase 7: Documentation ✅ / ❌ ### 7.1 Update CHANGELOG - [ ] Document all changes - [ ] List new fields added - [ ] List new services created - [ ] List API endpoints added - [ ] List frontend components added - [ ] Update to v1.1.0 **File:** `CHANGELOG.md` ### 7.2 Update API Documentation - [ ] Document `/api/v1/billing/limits/usage/` endpoint - [ ] Document error responses - [ ] Add examples **File:** `docs/20-API/BILLING-ENDPOINTS.md` ### 7.3 Update Feature Guide - [ ] Document plan limits feature - [ ] Document limit types - [ ] Document monthly reset - [ ] Add to features list **File:** `IGNY8-COMPLETE-FEATURES-GUIDE.md` --- ## Phase 8: Deployment ✅ / ❌ ### 8.1 Pre-Deployment Checklist - [ ] All migrations created and tested - [ ] All tests passing - [ ] No console errors in frontend - [ ] CHANGELOG updated - [ ] Version bumped to v1.1.0 - [ ] Code reviewed ### 8.2 Deployment Steps - [ ] Backup database - [ ] Run migrations - [ ] Deploy backend - [ ] Deploy frontend - [ ] Verify limits working - [ ] Monitor for errors ### 8.3 Post-Deployment Validation - [ ] Test limit checks work - [ ] Test usage tracking works - [ ] Test monthly reset (wait or trigger manually) - [ ] Verify no existing functionality broken - [ ] Monitor error logs --- ## 📊 Progress Summary **Total Tasks:** ~80 **Completed:** 2 **In Progress:** 1 **Not Started:** 77 **Estimated Time:** 8-12 hours **Started:** December 12, 2025 **Target Completion:** December 13, 2025 --- ## 🔍 Testing Scenarios ### Scenario 1: Hard Limit - Sites 1. Account with Starter plan (max 2 sites) 2. Create 2 sites successfully 3. Try to create 3rd site → should fail with limit error ### Scenario 2: Monthly Limit - Content Words 1. Account with Starter plan (100K words/month) 2. Generate content totaling 99K words 3. Try to generate 2K words → should fail 4. Wait for monthly reset 5. Generate 2K words → should succeed ### Scenario 3: Monthly Reset 1. Account at end of billing period 2. Has used 90% of limits 3. Run reset task 4. Verify usage reset to 0 5. Verify new period created ### Scenario 4: Plan Upgrade 1. Account on Starter plan 2. Reached 100% of limit 3. Upgrade to Growth plan 4. Verify new limits apply 5. Perform operation → should succeed --- ## ⚠️ Known Risks & Mitigation **Risk 1:** Breaking existing content generation **Mitigation:** Test thoroughly, use feature flags if needed **Risk 2:** Word count inconsistency **Mitigation:** Use single source (Content.word_count), standardize calculation **Risk 3:** Monthly reset errors **Mitigation:** Add error handling, logging, manual reset capability **Risk 4:** Performance impact of limit checks **Mitigation:** Optimize queries, add database indexes, cache plan data --- ## 📝 Notes - Use `Content.word_count` as single source of truth for word counting - Ignore `estimated_word_count` in Ideas and `word_count` in Tasks for limit tracking - Hard limits check COUNT from database - Monthly limits track usage in PlanLimitUsage table - Reset task must be idempotent (safe to run multiple times) - All limit checks happen server-side (frontend is informational only) - Use proper error classes for different limit types - Log all limit operations for debugging