skipRemoteCharts()) { return null; } $chartData = [ 'type' => 'bar', 'data' => [ 'labels' => ['Charges', 'Paid', 'Unpaid', 'Discounts', 'Refunds', 'Expenses', 'Reimbursements', 'Net'], 'datasets' => [[ 'label' => 'Amount (USD)', 'data' => [ $summary['totalCharges'] ?? 0, $summary['amountCollected'] ?? 0, $summary['totalUnpaid'] ?? 0, $summary['totalDiscounts'] ?? 0, $summary['totalRefunds'] ?? 0, $summary['totalExpenses'] ?? 0, $summary['totalReimbursements'] ?? 0, $summary['netAmount'] ?? 0, ], 'backgroundColor' => 'rgba(54, 162, 235, 0.6)', ]], ], ]; return $this->downloadChart($chartData, 'bar_chart.png'); } public function generatePieChart(array $summary): ?string { if ($this->skipRemoteCharts()) { return null; } $chartData = [ 'type' => 'pie', 'data' => [ 'labels' => ['Expenses', 'Reimbursements'], 'datasets' => [[ 'data' => [ $summary['totalExpenses'] ?? 0, $summary['totalReimbursements'] ?? 0, ], 'backgroundColor' => ['#e74c3c', '#8e44ad'], ]], ], ]; return $this->downloadChart($chartData, 'pie_chart.png'); } private function downloadChart(array $chartData, string $filename): ?string { $baseUrl = 'https://quickchart.io/chart?c='; $url = $baseUrl . urlencode(json_encode($chartData)); $targetDir = storage_path('app/reports'); if (!is_dir($targetDir) && !mkdir($targetDir, 0775, true) && !is_dir($targetDir)) { return null; } try { $contents = @file_get_contents($url); if ($contents === false) { return null; } $path = $targetDir . DIRECTORY_SEPARATOR . $filename; file_put_contents($path, $contents); return $path; } catch (\Throwable $e) { return null; } } private function skipRemoteCharts(): bool { if (app()->environment('testing')) { return true; } return (bool) config('services.quickchart.disabled', false); } }