number_format((float) $val, $val == floor($val) ? 0 : 2, ',', '.'); $now = now(); $today = $now->format('Y-m-d'); // 1. Egg Production by Unit - Single optimized query with joins $totalEggsByUnit = EggCollectionItem::query() ->join('egg_collections', 'egg_collection_items.egg_collection_id', 'egg_collections.id') ->join('units', 'egg_collection_items.unit_id', 'units.id') ->whereNull('egg_collections.deleted_at') ->where('egg_collections.production_date', $today) ->selectRaw('units.name as unit_name, sum(case when is_broken = 0 then quantity else 0 end) as total_good, sum(case when is_broken = 1 then quantity else 0 end) as total_broken') ->groupBy('units.name') ->get() ->map(fn ($item) => [ 'unit_name' => $item->unit_name, 'total_good' => $formatNumber($item->total_good), 'total_broken' => $formatNumber($item->total_broken), ]); // 2. Orders Stats - Combined count and sum $orderStats = Order::whereDate('order_date', $today) ->selectRaw('count(*) as count, sum(total_amount) as total') ->first(); $orderCount = (int) ($orderStats->count ?? 0); $orderRevenue = (float) ($orderStats->total ?? 0); // 3. Delayed Goods Stats - Combined sum and paid_amount $delayedStatsByUnit = DelayedGood::query() ->join('units', 'delayed_goods.unit_id', 'units.id') ->whereDate('delayed_goods.stored_date', $today) ->selectRaw('units.name as unit_name, sum(quantity) as total') ->groupBy('units.name') ->get() ->map(fn ($item) => [ 'unit_name' => $item->unit_name, 'total' => $formatNumber($item->total), ]); $delayedStatsTotals = DelayedGood::whereDate('stored_date', $today) ->selectRaw('sum(total_amount) as total, sum(paid_amount) as paid') ->first(); $delayedRevenue = (float) ($delayedStatsTotals->total ?? 0); $paidToday = (float) ($delayedStatsTotals->paid ?? 0); $totalRevenue = $orderRevenue + $delayedRevenue; // 4. Expenses & Financials Today $totalExpenses = (float) Expense::whereDate('expense_date', $today)->sum('amount'); $monthlyPayroll = (float) Payroll::where('period_month', $now->format('Y-m'))->sum('total_salary'); $totalFeedPurchase = (float) FeedPurchase::whereDate('purchase_date', $today)->sum('total_price'); $grossProfit = $totalRevenue - $totalFeedPurchase; $netProfit = $grossProfit - $totalExpenses - $monthlyPayroll; $totalReceivablesToday = $delayedRevenue - $paidToday; $mainStats = [ ['label' => 'Pesanan', 'desc' => 'Jumlah transaksi', 'value' => $orderCount, 'prefix' => ''], ['label' => 'Laba Bersih', 'desc' => 'Setelah dikurangi pengeluaran harian', 'value' => $formatNumber($netProfit), 'prefix' => 'Rp'], ['label' => 'Piutang', 'desc' => 'Piutang barang tertunda', 'value' => $formatNumber($totalReceivablesToday), 'prefix' => 'Rp'], ['label' => 'Pendapatan', 'desc' => 'Akumulasi pemasukan', 'value' => $formatNumber($totalRevenue), 'prefix' => 'Rp'], ['label' => 'Belanja Pakan', 'desc' => 'Baru dibeli', 'value' => $formatNumber($totalFeedPurchase), 'prefix' => 'Rp'], ]; // 5. Top Customers Today - Optimized summing $topCustomers = Customer::query() ->select('id', 'name', 'phone_number') ->withSum(['orders' => fn ($q) => $q->whereDate('order_date', $today)], 'total_amount') ->withSum(['delayedGoods' => fn ($q) => $q->whereDate('stored_date', $today)], 'total_amount') ->get() ->map(function ($customer) { $customer->total_spent = ($customer->orders_sum_total_amount ?? 0) + ($customer->delayed_goods_sum_total_amount ?? 0); return $customer; }) ->filter(fn ($c) => $c->total_spent > 0) ->sortByDesc('total_spent') ->take(5) ->values(); // 6. Distribution Charts Data $revenueSplitData = [ 'labels' => ['Penjualan Langsung', 'Barang Tertunda'], 'data' => [$orderRevenue, $delayedRevenue], ]; $expenseDistributionData = [ 'labels' => ['Belanja Pakan', 'Pengeluaran Umum'], 'data' => [$totalFeedPurchase, $totalExpenses], ]; $salesByUnit = Order::whereDate('order_date', $today) ->join('units', 'orders.unit_id', 'units.id') ->selectRaw('units.name, sum(total_amount) as total') ->groupBy('units.name') ->get(); return [ 'isAdministrator' => auth()->user()->hasRole(RoleEnum::ADMINISTRATOR->value), 'mainStats' => $mainStats, 'totalEggsByUnit' => $totalEggsByUnit, 'totalDelayedByUnit' => $delayedStatsByUnit, 'topCustomers' => $topCustomers, 'revenueSplit' => $revenueSplitData, 'expenseDistribution' => $expenseDistributionData, 'salesByUnit' => [ 'labels' => $salesByUnit->pluck('name')->values(), 'data' => $salesByUnit->pluck('total')->map(fn ($v) => (float) $v)->values(), ], 'formatNumber' => $formatNumber, ]; } }