Day 8 โ€“ Comparing Actual Sales vs Predicted Forecast in Laravel Dashboard #SalesForecastAI #ForecastAccuracy #LaravelDashboard #SalesAnalytics #AIInsights


Today weโ€™ll build a dashboard that visually compares actual sales vs forecasted predictions, and highlight any significant deviations โ€” helping you track accuracy and adjust strategy.


๐Ÿ“Š Step 1: Join actual & forecasted sales by date

In SalesController.php:

use App\Models\Sale;
use App\Models\ForecastResult;
use Illuminate\Support\Facades\DB;

public function index()
{
    // Historical daily sales
    $sales = Sale::select(
        DB::raw('DATE(sale_date) as date'),
        DB::raw('SUM(amount) as total')
    )
    ->groupBy('date')
    ->orderBy('date')
    ->get();

    // Forecast data
    $forecast = ForecastResult::orderBy('forecast_date')->get();

    // Align data
    $dates = $forecast->pluck('forecast_date')->map(fn($d) => date('d M', strtotime($d)));
    $actual = $dates->map(function ($d) use ($sales) {
        return $sales->firstWhere('date', date('Y-m-d', strtotime($d)))->total ?? null;
    });

    $predicted = $forecast->pluck('yhat');
    $lower = $forecast->pluck('yhat_lower');
    $upper = $forecast->pluck('yhat_upper');

    return view('sales.index', compact('dates', 'actual', 'predicted', 'lower', 'upper'));
}

๐Ÿ“ˆ Step 2: Update Chart.js to compare datasets

In sales/index.blade.php, replace chart setup:

<canvas id="forecastChart" height="120"></canvas>

<script>
const ctx = document.getElementById('forecastChart').getContext('2d');
new Chart(ctx, {
    type: 'line',
    data: {
        labels: @json($dates),
        datasets: [
            {
                label: 'Actual Sales',
                data: @json($actual),
                borderColor: 'rgba(54, 162, 235, 1)',
                backgroundColor: 'transparent',
                tension: 0.3,
                spanGaps: true
            },
            {
                label: 'Predicted Sales',
                data: @json($predicted),
                borderColor: 'rgba(255, 99, 132, 1)',
                borderDash: [5, 5],
                tension: 0.3
            },
            {
                label: 'Lower Bound',
                data: @json($lower),
                borderColor: 'rgba(200, 200, 200, 0.5)',
                fill: '+1',
                hidden: true
            },
            {
                label: 'Upper Bound',
                data: @json($upper),
                borderColor: 'rgba(200, 200, 200, 0.5)',
                fill: '-1',
                hidden: true
            }
        ]
    },
    options: {
        responsive: true,
        plugins: {
            legend: { position: 'top' },
            tooltip: { mode: 'index', intersect: false }
        },
        scales: {
            y: { beginAtZero: true }
        }
    }
});
</script>

๐Ÿ” Step 3: Interpret deviations manually or with GPT

In your insight generator (optional), add:

if (abs($actual - $predicted) > threshold) {
    $alert[] = "Sales on $date deviated significantly.";
}

Or use GPT again with a custom prompt:

“Compare actual sales vs predicted, highlight major gaps.”


โœ… Output

Your dashboard now clearly shows:

  • Actual vs Predicted sales lines
  • Visual gaps or convergence
  • Confidence band range (optional)
See also  Day 9: Logging AI Conversations into CRM for Customer Insights #AIVoiceBot #AIInsights

โœ… Up next (Day 9): weโ€™ll add CSV and PDF reports, allowing you to export forecasts and visual insights for management or reporting.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.