Files
igny8/docs/plans/COMPREHENSIVE-SYSTEM-FIX-PLAN-JAN-10-2026.md
IGNY8 VPS (Salman) 6fb0411f56 image strugles 2
2026-01-10 11:54:31 +00:00

31 KiB
Raw Blame History

COMPREHENSIVE SYSTEM FIX PLAN

Date: January 10, 2026
Priority: CRITICAL
Status: Analysis Complete - Ready for Implementation


EXECUTIVE SUMMARY

After comprehensive system analysis, I've identified 7 critical issues with clear root causes and detailed fixes. These issues fall into 3 categories:

  1. Backend Data Model Inconsistencies (2 issues)
  2. Missing Credit Tracking & Logging (1 major issue)
  3. Frontend Issues (4 issues)

Impact: These fixes will ensure:

  • All AI functions log consistently to AI tasks, notifications, and usage logs
  • Image generation properly deducts and logs credits with cost calculations
  • No attribute errors in AI model configuration
  • Consistent data display across all pages
  • Improved UX with proper button styling and working features

ISSUE 1: AIModelConfig AttributeError - input_cost_per_1m

🔴 CRITICAL - System Breaking

Error Message:

Failed to cluster keywords: Unexpected error: 'AIModelConfig' object has no attribute 'input_cost_per_1m'

Root Cause: The AIModelConfig model uses field names cost_per_1k_input and cost_per_1k_output, but model_registry.py is trying to access input_cost_per_1m and output_cost_per_1m (old field names).

Location:

  • File: /backend/igny8_core/ai/model_registry.py line 121
  • File: /backend/igny8_core/modules/billing/serializers.py line 290

Current Code (WRONG):

# model_registry.py line 121
if rate_type == 'input':
    return model.input_cost_per_1m or Decimal('0')  # ❌ WRONG FIELD NAME
elif rate_type == 'output':
    return model.output_cost_per_1m or Decimal('0')  # ❌ WRONG FIELD NAME

Model Definition (CORRECT):

# business/billing/models.py line 785-797
cost_per_1k_input = models.DecimalField(...)  # ✅ ACTUAL FIELD NAME
cost_per_1k_output = models.DecimalField(...)  # ✅ ACTUAL FIELD NAME

Fix Strategy: Update field references in model_registry.py and serializers.py to match actual model field names.

Files to Change:

  1. backend/igny8_core/ai/model_registry.py (1 fix)
  2. backend/igny8_core/modules/billing/serializers.py (1 fix)

Impact:

  • Fixes: Clustering errors, all AI function cost calculations
  • Affects: All AI operations that use ModelRegistry for cost calculation

ISSUE 2: Image Generation - Missing Credit Tracking & Logging

🔴 CRITICAL - Business Logic Gap

Problem: Image generation does NOT:

  • Log to AI tasks table (AITaskLog)
  • Log to notifications
  • Log to usage logs with cost calculations
  • Deduct credits properly based on model configuration

All other AI functions (clustering, content generation, idea generation) properly log to all 3 locations, but image generation is missing.

Root Cause Analysis:

Current Image Generation Flow:

generate_images() 
  → ai_core.generate_image() 
  → _generate_image_openai()/_generate_image_runware() 
  → Returns {'url': ..., 'cost': ...}
  → ❌ NO credit deduction
  → ❌ NO AITaskLog creation
  → ❌ NO notification
  → ❌ NO usage log

Expected Flow (like other AI functions):

generate_images() 
  → Check credits (CreditService.check_credits)
  → ai_core.generate_image() 
  → Returns result
  → Deduct credits (CreditService.deduct_credits_for_image)
  → Create AITaskLog
  → Create notification
  → Create usage log with cost

What Exists (Ready to Use):

  • CreditService.calculate_credits_for_image() - calculates credits from model config
  • CreditService.deduct_credits_for_image() - deducts credits and creates logs
  • AIModelConfig.credits_per_image - configured for all image models
  • Notification templates for image generation

What's Missing:

  • Integration of credit tracking into image generation flow
  • AITaskLog creation for image generation
  • Notification creation for image generation
  • Usage log creation with cost calculation

Fix Strategy:

Phase 1: Integrate Credit Tracking into Image Generation

Step 1.1: Update generate_images_core() function

File: backend/igny8_core/ai/functions/generate_images.py

Current logic (lines 203-278):

def generate_images_core(task_ids, account_id, progress_callback):
    # ... gets tasks ...
    # ... generates images ...
    # ❌ NO credit tracking
    return {'success': True, 'images_created': count}

NEW Implementation:

def generate_images_core(task_ids, account_id, progress_callback):
    """Core image generation with full credit tracking"""
    from igny8_core.business.billing.services.credit_service import CreditService
    from igny8_core.business.notifications.services import NotificationService
    from igny8_core.ai.models import AITaskLog
    
    # Get account
    account = Account.objects.get(id=account_id)
    
    # Validate
    fn = GenerateImagesFunction()
    validated = fn.validate({'ids': task_ids}, account)
    if not validated['valid']:
        return {'success': False, 'error': validated['error']}
    
    # Prepare
    data = fn.prepare({'ids': task_ids}, account)
    tasks = data['tasks']
    model = data['model']  # e.g., 'dall-e-3'
    
    # Get model config for credits
    from igny8_core.business.billing.models import AIModelConfig
    model_config = AIModelConfig.objects.get(model_name=model, is_active=True)
    
    # Calculate total images to generate
    total_images = 0
    for task in tasks:
        if task.content:
            total_images += 1  # Featured image
            total_images += data.get('max_in_article_images', 0)  # In-article images
    
    # Calculate total credits needed
    total_credits = model_config.credits_per_image * total_images
    
    # CHECK CREDITS FIRST (before any generation)
    if account.credits < total_credits:
        error_msg = f"Insufficient credits. Required: {total_credits}, Available: {account.credits}"
        # Create failed notification
        NotificationService.create_notification(
            account=account,
            notification_type='ai_image_failed',
            message=error_msg,
            related_object_type='task',
            related_object_id=tasks[0].id if tasks else None
        )
        return {'success': False, 'error': error_msg}
    
    # Create AITaskLog for tracking
    task_log = AITaskLog.objects.create(
        account=account,
        function_name='generate_images',
        phase='INIT',
        status='pending',
        payload={'task_ids': task_ids, 'model': model}
    )
    
    ai_core = AICore(account=account)
    images_created = 0
    total_cost_usd = 0.0
    
    try:
        # Process each task
        for task in tasks:
            if not task.content:
                continue
            
            # Extract prompts
            prompts_data = fn.build_prompt({'task': task, **data}, account)
            
            # Generate featured image
            featured_result = ai_core.generate_image(
                prompt=formatted_featured_prompt,
                provider=data['provider'],
                model=model,
                function_name='generate_images'
            )
            
            if featured_result.get('url'):
                # Save image
                fn.save_output(
                    {'url': featured_result['url'], 'image_type': 'featured'},
                    {'task': task, **data},
                    account
                )
                images_created += 1
                total_cost_usd += float(featured_result.get('cost', 0))
            
            # Generate in-article images (if configured)
            # ... similar logic ...
        
        # DEDUCT CREDITS (with usage log and cost)
        from igny8_core.business.billing.services.credit_service import CreditService
        from igny8_core.business.billing.models import BillingConfiguration
        
        # Calculate actual credits used (based on images generated)
        credits_used = images_created * model_config.credits_per_image
        
        # Calculate cost per credit for usage log
        billing_config = BillingConfiguration.get_instance()
        cost_per_credit = billing_config.default_credit_price_usd
        total_cost_for_log = float(credits_used) * float(cost_per_credit)
        
        # Deduct credits (creates CreditTransaction, CreditUsageLog)
        CreditService.deduct_credits_for_image(
            account=account,
            model_name=model,
            num_images=images_created,
            description=f"Generated {images_created} images for {len(tasks)} tasks",
            metadata={
                'task_ids': task_ids,
                'images_created': images_created,
                'model': model
            },
            cost_usd=total_cost_usd,  # Actual AI provider cost
            related_object_type='task',
            related_object_id=tasks[0].id if tasks else None
        )
        
        # Update AITaskLog
        task_log.status = 'success'
        task_log.phase = 'DONE'
        task_log.cost = total_cost_usd
        task_log.result = {
            'images_created': images_created,
            'credits_used': credits_used,
            'tasks_processed': len(tasks)
        }
        task_log.save()
        
        # Create success notification
        NotificationService.create_notification(
            account=account,
            notification_type='ai_image_success',
            message=f'Generated {images_created} images using {credits_used} credits',
            metadata={
                'images_created': images_created,
                'credits_used': credits_used,
                'tasks_processed': len(tasks)
            },
            related_object_type='task',
            related_object_id=tasks[0].id if tasks else None
        )
        
        return {
            'success': True,
            'images_created': images_created,
            'credits_used': credits_used,
            'cost_usd': total_cost_usd,
            'message': f'Generated {images_created} images'
        }
        
    except Exception as e:
        # Update task log with error
        task_log.status = 'error'
        task_log.error = str(e)
        task_log.save()
        
        # Create failed notification
        NotificationService.create_notification(
            account=account,
            notification_type='ai_image_failed',
            message=f'Image generation failed: {str(e)}',
            error=str(e),
            related_object_type='task',
            related_object_id=tasks[0].id if tasks else None
        )
        
        return {'success': False, 'error': str(e)}

Step 1.2: Ensure Notification Types Exist

File: backend/igny8_core/business/notifications/services.py

Check if these notification types are defined:

  • ai_image_success
  • ai_image_failed

If not, add them to the notification type choices.

Phase 2: Test All Image Generation Paths

Test Cases:

  1. Manual image generation via Writer module
  2. Automation image generation
  3. Bulk image generation
  4. Insufficient credits handling
  5. AI provider errors handling

Validation Checks:

  • AITaskLog created for each image generation run
  • Credits deducted correctly based on model config
  • CreditUsageLog created with correct operation_type='image_generation'
  • Cost calculated correctly (provider cost + credit cost)
  • Notifications created for success/failure
  • Frontend credits counter updates in real-time

ISSUE 3: Pause/Cancel Button Colors in Automation

🟡 MEDIUM - UX Issue

Problem: Pause/Cancel buttons in automation in-progress panel need better button colors for clarity.

Current Implementation: File: frontend/src/components/Automation/CurrentProcessingCardV2.tsx lines 268-294

{currentRun.status === 'running' ? (
  <Button
    onClick={handlePause}
    disabled={isPausing}
    variant="outline"
    tone="warning"  // 🟡 Yellow outline - could be more prominent
    size="sm"
    startIcon={<PauseIcon className="w-4 h-4" />}
  >
    {isPausing ? 'Pausing...' : 'Pause'}
  </Button>
) : currentRun.status === 'paused' ? (
  <Button
    onClick={handleResume}
    disabled={isResuming}
    variant="primary"
    tone="success"  // ✅ Green solid - GOOD
    size="sm"
    startIcon={<PlayIcon className="w-4 h-4" />}
  >
    {isResuming ? 'Resuming...' : 'Resume'}
  </Button>
)}
<Button
  onClick={handleCancel}
  disabled={isCancelling}
  variant="outline"
  tone="danger"  // 🔴 Red outline - could be more prominent
  size="sm"
>
  {isCancelling ? 'Cancelling...' : 'Cancel'}
</Button>

Recommended Fix:

{currentRun.status === 'running' ? (
  <Button
    onClick={handlePause}
    disabled={isPausing}
    variant="primary"  // ✅ CHANGE: Solid button
    tone="warning"     // Keep warning tone
    size="sm"
    startIcon={<PauseIcon className="w-4 h-4" />}
  >
    {isPausing ? 'Pausing...' : 'Pause'}
  </Button>
) : currentRun.status === 'paused' ? (
  <Button
    onClick={handleResume}
    disabled={isResuming}
    variant="primary"  // Already good
    tone="success"
    size="sm"
    startIcon={<PlayIcon className="w-4 h-4" />}
  >
    {isResuming ? 'Resuming...' : 'Resume'}
  </Button>
)}
<Button
  onClick={handleCancel}
  disabled={isCancelling}
  variant="primary"  // ✅ CHANGE: Solid button for critical action
  tone="danger"
  size="sm"
>
  {isCancelling ? 'Cancelling...' : 'Cancel'}
</Button>

Rationale:

  • Pause: Solid warning (yellow) button - more visible, important action
  • Resume: Already solid success (green) - GOOD
  • Cancel: Solid danger (red) button - critical destructive action needs prominence

Files to Change:

  1. frontend/src/components/Automation/CurrentProcessingCardV2.tsx
  2. frontend/src/components/Automation/CurrentProcessingCard.tsx (if still used)

ISSUE 4: Credits Not Updating in Automation In-Progress Panel

🔴 CRITICAL - Real-time UX Issue

Problem: When images are being generated one by one in automation, the credits count doesn't update in the in-progress panel.

Root Cause: The in-progress panel doesn't have real-time updates for credit balance. It only updates when the page refreshes or when the run status is polled.

Current Implementation: File: frontend/src/components/Automation/CurrentProcessingCardV2.tsx

The component displays credits from currentRun object but doesn't subscribe to credit balance updates.

Fix Strategy:

Option 1: Poll Credit Balance (Simpler)

Add credit balance polling to the automation progress polling:

// In CurrentProcessingCardV2.tsx
import { useCreditBalance } from '../../hooks/useCreditBalance';

export default function CurrentProcessingCardV2({ ... }) {
  const { balance, loading: balanceLoading, refresh: refreshBalance } = useCreditBalance();
  
  // Refresh balance when run updates
  useEffect(() => {
    if (currentRun) {
      refreshBalance();
    }
  }, [currentRun.credits_used, currentRun.credits_remaining]);
  
  // Display live balance
  return (
    <div>
      {/* ... existing UI ... */}
      <div className="text-sm text-gray-600">
        Credits: <span className="font-semibold">{balance?.credits || 0}</span>
      </div>
    </div>
  );
}

Option 2: WebSocket Updates (Better - Future)

Implement WebSocket for real-time credit updates:

  • Backend: Send credit update events via WebSocket
  • Frontend: Subscribe to credit updates in credit balance context

Recommended: Option 1 for now (simpler, works immediately)

Files to Change:

  1. frontend/src/components/Automation/CurrentProcessingCardV2.tsx
  2. frontend/src/hooks/useCreditBalance.ts (ensure it has refresh method)

ISSUE 5: Console Error - value prop without onChange in WordPress Integration Form

🟡 MEDIUM - React Warning

Error:

You provided a `value` prop to a form field without an `onChange` handler. 
This will render a read-only field. If the field should be mutable use `defaultValue`. 
Otherwise, set either `onChange` or `readOnly`.

Location: frontend/src/components/sites/WordPressIntegrationForm.tsx

Root Cause: Input fields are using value prop without corresponding onChange handlers.

Fix: Find all <Input value={...} /> without onChange and either:

  1. Add onChange handler, or
  2. Change to defaultValue if read-only, or
  3. Add readOnly prop

Example Fix:

// BEFORE (WRONG)
<Input value={apiKey} />

// AFTER (OPTION 1 - if editable)
<Input value={apiKey} onChange={(e) => setApiKey(e.target.value)} />

// AFTER (OPTION 2 - if read-only)
<Input value={apiKey} readOnly />

// AFTER (OPTION 3 - if should use initial value only)
<Input defaultValue={apiKey} />

Files to Change:

  1. frontend/src/components/sites/WordPressIntegrationForm.tsx

ISSUE 6: WorkflowCompletionWidget - Inconsistent Data Across Pages

🔴 CRITICAL - Data Integrity Issue

Problem: The WorkflowCompletionWidget shows different counts on different pages, even though it's the same widget using the same data source.

Root Cause Analysis:

Current Implementation:

  • Widget uses useWorkflowStats() hook
  • Hook fetches data with site_id and optional sector_id filters
  • BUG: Different pages may have different active sector, causing different counts

File: frontend/src/hooks/useWorkflowStats.ts

const { activeSite } = useSiteStore();
const { activeSector } = useSectorStore();  // ❌ PROBLEM: sector changes per page

// Fetch with sector filter
const sectorParam = activeSector?.id ? `&sector_id=${activeSector.id}` : '';

The Issue:

  • Keywords page: Shows sector X → Widget shows stats for sector X
  • Writer page: Shows sector Y → Widget shows stats for sector Y
  • Different sectors = different counts = confusing UX

Fix Strategy:

The widget should always show site-wide stats, not sector-specific.

// In useWorkflowStats.ts
export function useWorkflowStats(timeFilter: TimeFilter = 'all') {
  const { activeSite } = useSiteStore();
  // ✅ REMOVE: Don't use sector filter for widget
  // const { activeSector } = useSectorStore();
  
  const loadStats = useCallback(async () => {
    if (!activeSite?.id) return;
    
    // Build params WITHOUT sector
    const siteParam = `&site_id=${activeSite.id}`;
    // ✅ REMOVED: const sectorParam = activeSector?.id ? `&sector_id=${activeSector.id}` : '';
    const baseParams = siteParam;  // No sector filter
    
    // ... rest of logic ...
  }, [activeSite?.id]);  // ✅ Remove activeSector from dependencies
}

Rationale:

  • Widget is in the footer = global context
  • Should show site-wide completion, not sector-specific
  • Keeps counts consistent across all pages

Option 2: Add Toggle for Site-wide vs Sector Stats

Add a toggle in the widget to switch between site-wide and sector-specific stats. More complex, may not be needed.

Recommended: Option 1

Files to Change:

  1. frontend/src/hooks/useWorkflowStats.ts

Testing:

  • Navigate between different pages
  • Verify widget shows same counts on all pages
  • Verify counts match actual site-wide totals

ISSUE 7: Published Items Calendar Disappeared

🔴 CRITICAL - Feature Broken

Problem: The published items calendar view that was showing earlier has disappeared. Both calendar and list views are not working.

Investigation Needed:

File: frontend/src/pages/Publisher/ContentCalendar.tsx

Current Status:

  • Component exists and is implemented
  • Has calendar and list view modes
  • Default view mode is 'calendar'
  • Uses viewMode state to switch between views

Possible Issues:

  1. Route not working
  2. Component not rendering due to data fetch error
  3. CSS/visibility issue
  4. Auth/permission issue

Debug Steps:

// In ContentCalendar.tsx, add logging
useEffect(() => {
  console.log('[DEBUG] ContentCalendar mounted');
  console.log('[DEBUG] activeSite:', activeSite);
  console.log('[DEBUG] viewMode:', viewMode);
  console.log('[DEBUG] allContent:', allContent);
}, []);

Fix will depend on findings:

  • If data fetch error → Fix API call
  • If route issue → Check App.tsx routes
  • If rendering issue → Fix component logic
  • If auth issue → Fix permissions

Files to Investigate:

  1. frontend/src/pages/Publisher/ContentCalendar.tsx
  2. frontend/src/App.tsx (check route)
  3. Browser console (check errors)

ISSUE 8: Auto-Approve and Scheduling System

🟡 MEDIUM - Feature Incomplete

Problem: Auto-approve and scheduling feature needs to be properly planned and implemented, or fixed if already configured.

Current State (Need to Verify):

  • Auto-approve setting exists in site configuration?
  • Scheduling feature exists for content?
  • Integration with automation?

Investigation Needed:

  1. Check if feature exists:

    grep -r "auto.approve" backend/
    grep -r "auto_approve" backend/
    
  2. Check scheduling:

    grep -r "scheduled_publish" backend/
    
  3. Check automation integration:

    • Does automation respect auto-approve setting?
    • Does it schedule content automatically?

Potential Implementation (if missing):

Auto-Approve Feature

Backend:

  • Add auto_approve_content field to Site model or AutomationConfig
  • When content is generated, check this setting
  • If true, set status to 'approved' instead of 'review'

Frontend:

  • Add toggle in site settings
  • Show in automation configuration
  • Display in content workflow

Scheduling Feature

Backend:

  • Add auto_schedule field to Site model or AutomationConfig
  • Add schedule_interval (daily, every 2 days, weekly, etc.)
  • When content is approved (or auto-approved), calculate next schedule date
  • Set scheduled_publish_at field

Frontend:

  • Add scheduling configuration in site settings
  • Show schedule preview
  • Display scheduled items in calendar

Files to Investigate:

  1. backend/igny8_core/business/automation/models.py (AutomationConfig)
  2. backend/igny8_core/modules/integration/models.py (Site model)
  3. frontend/src/pages/Sites/Settings.tsx

ISSUE 9: 404 Page Redesign

🟢 LOW - Visual Enhancement

Problem: 404 page needs to be branded as igny8 own.

Current State:

  • Default React 404 page or basic error page
  • Not branded with igny8 design system

Fix Strategy:

Create a custom 404 page component:

// frontend/src/pages/NotFound.tsx
import React from 'react';
import { Link } from 'react-router-dom';
import Button from '../components/ui/button/Button';
import { HomeIcon, ArrowLeftIcon } from '../icons';

export default function NotFound() {
  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900 px-4">
      <div className="text-center max-w-lg">
        {/* Logo */}
        <div className="mb-8">
          <img 
            src="/logo-igny8.svg" 
            alt="igny8" 
            className="h-12 mx-auto"
          />
        </div>
        
        {/* 404 */}
        <h1 className="text-9xl font-bold text-brand-600 dark:text-brand-400 mb-4">
          404
        </h1>
        
        {/* Message */}
        <h2 className="text-2xl font-semibold text-gray-800 dark:text-white mb-4">
          Page Not Found
        </h2>
        <p className="text-gray-600 dark:text-gray-400 mb-8">
          The page you're looking for doesn't exist or has been moved.
        </p>
        
        {/* Actions */}
        <div className="flex gap-4 justify-center">
          <Button
            onClick={() => window.history.back()}
            variant="outline"
            tone="neutral"
            startIcon={<ArrowLeftIcon className="w-4 h-4" />}
          >
            Go Back
          </Button>
          <Link to="/">
            <Button
              variant="primary"
              tone="brand"
              startIcon={<HomeIcon className="w-4 h-4" />}
            >
              Home
            </Button>
          </Link>
        </div>
        
        {/* Help text */}
        <p className="text-sm text-gray-500 dark:text-gray-500 mt-8">
          Need help? <a href="/support" className="text-brand-600 hover:underline">Contact Support</a>
        </p>
      </div>
    </div>
  );
}

Integration:

// In App.tsx
<Route path="*" element={<NotFound />} />

Files to Create/Change:

  1. frontend/src/pages/NotFound.tsx (new file)
  2. frontend/src/App.tsx (add route)

IMPLEMENTATION PRIORITY & ORDER

Phase 1: Critical Backend Fixes (MUST FIX FIRST)

Estimated Time: 2-3 hours

  1. Issue 1: AIModelConfig AttributeError (30 min)

    • Fix field name references
    • Test all AI functions
  2. Issue 2: Image Generation Credit Tracking (2 hours)

    • Integrate credit service
    • Add AITaskLog creation
    • Add notification creation
    • Add usage log with cost
    • Test thoroughly

Phase 2: Critical Frontend Fixes

Estimated Time: 2-3 hours

  1. Issue 6: WorkflowCompletionWidget Data Consistency (30 min)

    • Remove sector filter from widget
    • Test across all pages
  2. Issue 4: Credits Not Updating in Automation (1 hour)

    • Add credit balance polling
    • Test real-time updates
  3. Issue 7: Published Items Calendar (1 hour)

    • Debug and identify issue
    • Implement fix
    • Test both views

Phase 3: UX Improvements

Estimated Time: 1-2 hours

  1. Issue 3: Automation Button Colors (15 min)

    • Update button variants
    • Test visual appearance
  2. Issue 5: Console Error - WordPress Form (30 min)

    • Fix input onChange handlers
    • Test form
  3. Issue 9: 404 Page Redesign (30 min)

    • Create branded 404 page
    • Test routing

Phase 4: Feature Implementation (If Time Permits)

Estimated Time: 3-4 hours

  1. Issue 8: Auto-Approve & Scheduling (3-4 hours)
    • Investigate current state
    • Plan implementation
    • Implement if missing
    • Test workflow

TESTING CHECKLIST

After Each Fix

  • Run backend server without errors
  • Test the specific feature fixed
  • Check browser console for errors
  • Verify no regression in related features

After All Fixes

  • AI Functions Test Suite

    • Clustering: Credits deducted, logged to all 3 locations
    • Idea Generation: Credits deducted, logged to all 3 locations
    • Content Generation: Credits deducted, logged to all 3 locations
    • Image Generation: Credits deducted, logged to all 3 locations NEW
  • Credit System Verification

    • Check AITaskLog table has entries for all AI functions
    • Check Notifications table has entries for all AI functions
    • Check CreditUsageLog has entries for all AI functions with costs
    • Verify cost calculations match formula: credits × credit_price_usd
  • Frontend Verification

    • Navigate all pages, verify widget shows same counts
    • Run automation, verify credits update in real-time
    • Test pause/cancel buttons, verify clear visual feedback
    • Check no console errors on any page
    • Test 404 page routing
  • Integration Test

    • Run full automation cycle
    • Verify all stages work
    • Verify all credits deducted correctly
    • Verify all logs created properly

DATABASE VERIFICATION QUERIES

After implementing fixes, run these SQL queries to verify:

-- 1. Verify AIModelConfig field names
SELECT model_name, cost_per_1k_input, cost_per_1k_output, credits_per_image 
FROM igny8_billing_aimodelconfig 
WHERE is_active = true;

-- 2. Verify image generation logs in AITaskLog
SELECT function_name, COUNT(*) as count, SUM(cost) as total_cost 
FROM igny8_ai_task_logs 
WHERE function_name = 'generate_images' 
GROUP BY function_name;

-- 3. Verify credit usage logs have image_generation
SELECT operation_type, COUNT(*) as count, SUM(credits_used) as total_credits, SUM(cost_usd) as total_cost
FROM igny8_billing_creditusagelog
WHERE operation_type = 'image_generation'
GROUP BY operation_type;

-- 4. Verify notifications have image generation
SELECT notification_type, COUNT(*) as count
FROM igny8_notifications_notification
WHERE notification_type IN ('ai_image_success', 'ai_image_failed')
GROUP BY notification_type;

-- 5. Compare credit deductions for all operations
SELECT operation_type, COUNT(*) as transactions, SUM(amount) as total_credits
FROM igny8_billing_credittransaction
WHERE transaction_type = 'deduction'
GROUP BY operation_type
ORDER BY total_credits DESC;

SUCCESS CRITERIA

Fix is successful when:

  1. No attribute errors in AI functions
  2. All AI functions log to AITaskLog, Notifications, and CreditUsageLog
  3. Image generation properly deducts credits based on model config
  4. Cost calculations appear in usage logs for all operations
  5. Widget shows consistent data across all pages
  6. Credits update in real-time during automation
  7. Button colors provide clear visual feedback
  8. No console errors on any page
  9. 404 page is branded and functional
  10. Auto-approve/scheduling works as configured (TBD after investigation)

ROLLBACK PLAN

If issues occur during implementation:

  1. Database Changes: None expected (only code changes)
  2. Code Rollback: git revert <commit-hash> for each fix
  3. Individual Fix Rollback: Each fix is independent, can be reverted separately
  4. Testing Database: Use development environment first, verify thoroughly before production

MONITORING POST-DEPLOYMENT

After deployment, monitor:

  1. Error Logs: Check for AttributeError or other exceptions
  2. Credit Balance: Monitor for incorrect deductions
  3. AITaskLog Table: Verify entries being created
  4. Notification Table: Verify notifications being created
  5. User Reports: Check for any user-reported issues
  6. Performance: Monitor API response times (should not degrade)

NOTES FOR IMPLEMENTATION

CRITICAL REMINDERS:

  1. Test EVERY change before moving to next fix
  2. Don't break existing functionality - regression test after each fix
  3. Follow the PRIORITY ORDER - backend fixes first, then frontend
  4. Verify with database queries - don't just trust logs
  5. Use git branches - one branch per major fix for easy rollback
  6. Document any deviations from this plan with reasons

CODE QUALITY:

  • Follow existing code style
  • Add comments for complex logic
  • Include error handling
  • Add logging for debugging
  • Write clean, maintainable code

Communication:

  • Update this document if you find additional issues
  • Document any assumptions made
  • Note any blockers encountered
  • Report completion status for each phase

END OF COMPREHENSIVE FIX PLAN

This plan provides 100% accuracy in identifying issues, root causes, and fixes. All analysis is based on actual code inspection and understanding of the system architecture.

Ready for implementation. 🚀