input('date_start', Carbon::now()->toDateString()); $dateEnd = $request->input('date_end', Carbon::now()->toDateString()); // 1. Get Purchase Orders (Completed or Received that are ready for accounting) $purchaseOrders = PurchaseOrder::with(['vendor']) ->whereIn('status', ['received', 'completed']) ->whereBetween('created_at', [$dateStart . ' 00:00:00', $dateEnd . ' 23:59:59']) ->get() ->map(function ($po) { return [ 'id' => 'PO-' . $po->id, 'date' => Carbon::parse($po->created_at)->timezone(config('app.timezone'))->toDateString(), 'source' => '採購單', 'category' => '進貨支出', 'item' => $po->vendor->name ?? '未知廠商', 'reference' => $po->code, 'invoice_number' => $po->invoice_number, 'amount' => $po->grand_total, ]; }); // 2. Get Utility Fees $utilityFees = UtilityFee::whereBetween('transaction_date', [$dateStart, $dateEnd]) ->get() ->map(function ($fee) { return [ 'id' => 'UF-' . $fee->id, 'date' => $fee->transaction_date->format('Y-m-d'), 'source' => '公共事業費', 'category' => $fee->category, 'item' => $fee->description ?: $fee->category, 'reference' => '-', 'invoice_number' => $fee->invoice_number, 'amount' => $fee->amount, ]; }); // Combine and Sort $allRecords = $purchaseOrders->concat($utilityFees) ->sortByDesc('date') ->values(); // 3. Manual Pagination $perPage = $request->input('per_page', 10); $page = $request->input('page', 1); $offset = ($page - 1) * $perPage; $paginatedRecords = new LengthAwarePaginator( $allRecords->slice($offset, $perPage)->values(), $allRecords->count(), $perPage, $page, ['path' => $request->url(), 'query' => $request->query()] ); $summary = [ 'total_amount' => $allRecords->sum('amount'), 'purchase_total' => $purchaseOrders->sum('amount'), 'utility_total' => $utilityFees->sum('amount'), 'record_count' => $allRecords->count(), ]; return Inertia::render('Accounting/Report', [ 'records' => $paginatedRecords, 'summary' => $summary, 'filters' => [ 'date_start' => $dateStart, 'date_end' => $dateEnd, 'per_page' => (int)$perPage, ], ]); } public function export(Request $request) { $dateStart = $request->input('date_start', Carbon::now()->toDateString()); $dateEnd = $request->input('date_end', Carbon::now()->toDateString()); $selectedIdsParam = $request->input('selected_ids'); $purchaseOrdersQuery = PurchaseOrder::with(['vendor']) ->whereIn('status', ['received', 'completed']); $utilityFeesQuery = UtilityFee::query(); if ($selectedIdsParam) { $ids = explode(',', $selectedIdsParam); $poIds = []; $ufIds = []; foreach ($ids as $id) { if (str_starts_with($id, 'PO-')) { $poIds[] = substr($id, 3); } elseif (str_starts_with($id, 'UF-')) { $ufIds[] = substr($id, 3); } } $purchaseOrders = $purchaseOrdersQuery->whereIn('id', $poIds)->get(); $utilityFees = $utilityFeesQuery->whereIn('id', $ufIds)->get(); } else { $purchaseOrders = $purchaseOrdersQuery ->whereBetween('created_at', [$dateStart . ' 00:00:00', $dateEnd . ' 23:59:59']) ->get(); $utilityFees = $utilityFeesQuery ->whereBetween('transaction_date', [$dateStart, $dateEnd]) ->get(); } $allRecords = collect(); foreach ($purchaseOrders as $po) { $allRecords->push([ Carbon::parse($po->created_at)->toDateString(), '採購單', '進貨支出', $po->vendor->name ?? '', $po->code, $po->invoice_number, (float)$po->grand_total, ]); } foreach ($utilityFees as $fee) { $allRecords->push([ Carbon::parse($fee->transaction_date)->toDateString(), '公共事業費', $fee->category, $fee->description, '-', $fee->invoice_number, (float)$fee->amount, ]); } $allRecords = $allRecords->sortByDesc(0); $filename = "accounting_report_{$dateStart}_{$dateEnd}.csv"; $headers = [ 'Content-Type' => 'text/csv; charset=UTF-8', 'Content-Disposition' => "attachment; filename=\"{$filename}\"", ]; $callback = function () use ($allRecords) { $file = fopen('php://output', 'w'); // BOM for Excel compatibility with UTF-8 fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF)); fputcsv($file, ['日期', '來源', '類別', '項目', '參考單號', '發票號碼', '金額']); foreach ($allRecords as $row) { fputcsv($file, $row); } fclose($file); }; return response()->stream($callback, 200, $headers); } }