$this->getStats($today, $yesterday, fn ($date) => Order::whereDate('created_at', $date)->count()), 'total_pendapatan' => $this->getStats($today, $yesterday, fn ($date) => Order::whereDate('created_at', $date)->sum('total')), 'total_pengeluaran' => $this->getStats($today, $yesterday, fn ($date) => Expense::whereDate('created_at', $date)->sum('amount')), 'hpp' => $this->getStats($today, $yesterday, fn ($date) => Order::whereDate('created_at', $date)->sum('hpp')), 'total_diskon' => $this->getStats($today, $yesterday, fn ($date) => Order::whereDate('created_at', $date)->sum('discount')), 'total_pembelian' => $this->getStats($today, $yesterday, fn ($date) => Purchase::whereDate('created_at', $date)->sum('total')), 'produk_terjual' => $this->getStats($today, $yesterday, fn ($date) => OrderItem::whereHas('order', fn ($q) => $q->whereDate('created_at', $date))->sum('qty')), 'total_pelanggan' => $this->getStats($today, $yesterday, fn ($date) => Order::whereDate('created_at', $date)->distinct('customer_name')->count('customer_name')), ]; // Complex stats $stats['aov'] = $this->calculateAov($stats['total_pendapatan'], $stats['total_penjualan']); $stats['laba_kotor'] = $this->calculateDiff($stats['total_pendapatan'], $stats['hpp']); $stats['laba_bersih'] = $this->calculateDiff($stats['laba_kotor'], $stats['total_pengeluaran']); $stats['profit_margin'] = $this->calculateMargin($stats['laba_bersih'], $stats['total_pendapatan']); // Chart Data $stats['charts'] = [ 'jam_sibuk' => $this->getJamSibuk($today, $yesterday), 'order_by_payment' => $this->getOrderByEnum($today, 'payment_method', \App\Enums\PaymentMethod::class), 'order_by_status' => $this->getOrderByEnum($today, 'order_status', \App\Enums\OrderStatus::class), 'order_by_channel' => $this->getOrderByEnum($today, 'order_channel', \App\Enums\OrderChannel::class), 'top_products' => $this->getTopProducts($today), ]; return Inertia::render('dashboard', [ 'stats' => $stats, ]); } private function getJamSibuk($today, $yesterday) { $todayData = Order::whereDate('created_at', $today) ->selectRaw('HOUR(created_at) as hour, count(*) as count') ->groupBy('hour') ->pluck('count', 'hour') ->toArray(); $yesterdayData = Order::whereDate('created_at', $yesterday) ->selectRaw('HOUR(created_at) as hour, count(*) as count') ->groupBy('hour') ->pluck('count', 'hour') ->toArray(); $chartData = []; for ($i = 0; $i < 24; $i++) { $chartData[] = [ 'hour' => sprintf('%02d:00', $i), 'today' => $todayData[$i] ?? 0, 'yesterday' => $yesterdayData[$i] ?? 0, ]; } return $chartData; } private function getOrderByEnum($date, $column, $enumClass) { $data = Order::whereDate('created_at', $date) ->selectRaw("$column, count(*) as count") ->groupBy($column) ->get(); return $data->map(function($item) use ($column, $enumClass) { $enumValue = $item->$column; $label = $enumValue instanceof $enumClass ? $enumValue->label() : $enumValue; return [ 'name' => $label, 'value' => $item->count, ]; }); } private function getTopProducts($date) { return OrderItem::whereHas('order', fn($q) => $q->whereDate('created_at', $date)) ->with('product:id,name') ->selectRaw('product_id, sum(qty) as total_qty') ->groupBy('product_id') ->orderByDesc('total_qty') ->limit(5) ->get() ->map(fn($item) => [ 'name' => $item->product->name ?? 'Unknown', 'qty' => (int) $item->total_qty, ]); } private function getStats($today, $yesterday, $callback) { $todayVal = $callback($today); $yesterdayVal = $callback($yesterday); return [ 'value' => $todayVal, 'yesterday' => $yesterdayVal, 'change' => $this->calculatePercentageChange($todayVal, $yesterdayVal), ]; } private function calculatePercentageChange($current, $previous) { if ($previous == 0) { return $current > 0 ? 100 : 0; } return round((($current - $previous) / $previous) * 100, 2); } private function calculateAov($revenue, $sales) { $todayVal = $sales['value'] > 0 ? $revenue['value'] / $sales['value'] : 0; $yesterdayVal = $sales['yesterday'] > 0 ? $revenue['yesterday'] / $sales['yesterday'] : 0; return [ 'value' => $todayVal, 'yesterday' => $yesterdayVal, 'change' => $this->calculatePercentageChange($todayVal, $yesterdayVal), ]; } private function calculateDiff($a, $b) { $todayVal = $a['value'] - $b['value']; $yesterdayVal = $a['yesterday'] - $b['yesterday']; return [ 'value' => $todayVal, 'yesterday' => $yesterdayVal, 'change' => $this->calculatePercentageChange($todayVal, $yesterdayVal), ]; } private function calculateMargin($profit, $revenue) { $todayVal = $revenue['value'] > 0 ? ($profit['value'] / $revenue['value']) * 100 : 0; $yesterdayVal = $revenue['yesterday'] > 0 ? ($profit['yesterday'] / $revenue['yesterday']) * 100 : 0; return [ 'value' => round($todayVal, 2), 'yesterday' => round($yesterdayVal, 2), 'change' => $this->calculatePercentageChange($todayVal, $yesterdayVal), ]; } }