@extends('reports.pdf.layout') @section('title', $data['meta']['title']) @php use Illuminate\Support\Number; $meta = $data['meta']; $kpis = $data['kpis_strategic']; $safety = $data['kpis_safety']; $series = $data['monthly_series']; $break = $data['expense_breakdown']; $fmtNum = function ($v, $unit = '') { if ($v === null) return '—'; $s = is_numeric($v) ? number_format((float) $v, 0, ',', ' ') : (string) $v; return trim($s . ' ' . $unit); }; $fmtDelta = function ($v, $unit = '%') { if ($v === null) return null; $sign = $v > 0 ? '+' : ''; return $sign . number_format((float) $v, 1, ',', ' ') . $unit; }; $deltaClass = function ($v, bool $maximize = true) { if ($v === null || $v == 0) return 'delta-flat'; $up = $v > 0; return ($up === $maximize) ? 'delta-up' : 'delta-down'; }; // Pie chart geometry — single SVG slice path per segment. A 360° slice // (single category covering 100%) collapses to a degenerate arc that // wkhtmltopdf won't render, so we mark those for a full-circle fallback. $pieRadius = 60; $pieCx = 70; $pieCy = 70; $pieColors = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#06B6D4', '#EC4899', '#6B7280']; $totalPie = array_sum(array_map(fn ($b) => $b['amount'], $break)); $pieSlices = []; $accAngle = -90; foreach ($break as $i => $b) { if ($totalPie <= 0) break; $sweep = ($b['amount'] / $totalPie) * 360; $isFull = $sweep >= 359.999; if ($isFull) { $path = null; // renderer draws a instead } else { $rad1 = deg2rad($accAngle); $rad2 = deg2rad($accAngle + $sweep); $x1 = $pieCx + $pieRadius * cos($rad1); $y1 = $pieCy + $pieRadius * sin($rad1); $x2 = $pieCx + $pieRadius * cos($rad2); $y2 = $pieCy + $pieRadius * sin($rad2); $largeArc = $sweep > 180 ? 1 : 0; $path = sprintf( 'M %s %s L %.2f %.2f A %s %s 0 %d 1 %.2f %.2f Z', $pieCx, $pieCy, $x1, $y1, $pieRadius, $pieRadius, $largeArc, $x2, $y2 ); } $pieSlices[] = [ 'path' => $path, 'color' => $pieColors[$i % count($pieColors)], 'label' => $b['label'], 'pct' => $b['percent'], 'amt' => $b['amount'], ]; $accAngle += $sweep; } // Line chart geometry — TCO per vehicle over the months. $chartW = 480; $chartH = 140; $padX = 30; $padY = 18; $values = array_filter(array_map(fn ($r) => $r['tco_per_vehicle'], $series), fn ($v) => $v !== null); $minV = !empty($values) ? min($values) : 0; $maxV = !empty($values) ? max($values) : 1; if ($minV === $maxV) { $maxV = $minV + 1; } $stepX = count($series) > 1 ? ($chartW - 2 * $padX) / (count($series) - 1) : 0; $points = []; foreach ($series as $i => $r) { if ($r['tco_per_vehicle'] === null) continue; $x = $padX + $i * $stepX; $y = $chartH - $padY - (($r['tco_per_vehicle'] - $minV) / ($maxV - $minV)) * ($chartH - 2 * $padY); $points[] = ['x' => $x, 'y' => $y, 'label' => $r['label'], 'value' => $r['tco_per_vehicle']]; } $polyline = implode(' ', array_map(fn ($p) => "{$p['x']},{$p['y']}", $points)); @endphp @section('content')
DADYCAR FLEET MANAGER

{{ $meta['title'] }}

Synthèse globale {{ $meta['code'] }} Période : {{ $meta['period']['label'] }} · {{ $meta['site_label'] }} · {{ $meta['total_vehicles'] }} véhicules · Généré le {{ $meta['generated_at']->locale('fr')->isoFormat('D MMMM YYYY') }}

Indicateurs stratégiques

TCO moyen / véhicule
{{ $fmtNum($kpis['tco_per_vehicle']['value']) }}{{ $kpis['tco_per_vehicle']['unit'] }}
@if ($kpis['tco_per_vehicle']['delta'] !== null)
{{ $fmtDelta($kpis['tco_per_vehicle']['delta']) }} {{ $kpis['tco_per_vehicle']['delta_label'] }}
@else
{{ $kpis['tco_per_vehicle']['delta_label'] }}
@endif
Taux de disponibilité
{{ $fmtNum($kpis['availability']['value']) }}{{ $kpis['availability']['unit'] }}
{{ $kpis['availability']['delta_label'] }}
Score éco-conduite
{{ $fmtNum($kpis['eco_score']['value']) }}{{ $kpis['eco_score']['unit'] }}
{{ $kpis['eco_score']['delta_label'] }}
Coût total
{{ $fmtNum($kpis['total_cost']['value']) }}{{ $kpis['total_cost']['unit'] }}
@if ($kpis['total_cost']['delta'] !== null)
{{ $fmtDelta($kpis['total_cost']['delta']) }} vs période précédente
@else
{{ $kpis['total_cost']['delta_label'] }}
@endif

Évolution mensuelle — TCO par véhicule (6 mois)

@if (!empty($points)) {{-- wkhtmltopdf 0.12.x renders SVGs with width="100%" at 0×0 — pin pixel size. --}} @foreach ($points as $p) {{ $p['label'] }} {{ number_format($p['value'], 0, ',', ' ') }} @endforeach @else

Pas de données de coût pour la période.

@endif

Répartition des dépenses ({{ $meta['period']['label'] }})

@if (!empty($pieSlices))
@foreach ($pieSlices as $s) @if ($s['path'] === null) @else @endif @endforeach @foreach ($pieSlices as $s)
{{ $s['label'] }} — {{ number_format($s['amt'], 0, ',', ' ') }} € ({{ number_format($s['pct'], 1, ',', ' ') }} %)
@endforeach
@else

Aucune dépense dans la période.

@endif

Résumé exécutif — Points clés

@php $kpToneBg = ['success' => '#D1FAE5', 'warning' => '#FEF3C7', 'danger' => '#FEE2E2', 'neutral' => '#F3F4F6']; $kpToneColor = ['success' => '#065F46', 'warning' => '#92400E', 'danger' => '#991B1B', 'neutral' => '#374151']; $kpIcon = ['success' => '✓', 'warning' => '!', 'danger' => '✕', 'neutral' => '·']; @endphp @if (!empty($data['key_points'])) @foreach ($data['key_points'] as $p) @php $tone = $p['status'] ?? 'neutral'; $bg = $kpToneBg[$tone] ?? $kpToneBg['neutral']; $fg = $kpToneColor[$tone] ?? $kpToneColor['neutral']; @endphp
{{ $kpIcon[$tone] ?? '·' }} {{ $p['label'] }}
@endforeach @else

Aucun point clé.

@endif

Sécurité & Conformité

Sinistres ouverts
{{ $fmtNum($safety['open_claims']['value']) }}
@php $cl = $safety['open_claims']; @endphp @if (!empty($cl['delta']) || $cl['delta'] === 0)
@if ($cl['delta'] !== null && $cl['delta'] !== 0){{ ($cl['delta'] > 0 ? '+' : '') . $cl['delta'] }} @endif{{ $cl['delta_label'] }}
@else
{{ $cl['delta_label'] }}
@endif
Taux de conformité
{{ $fmtNum($safety['compliance']['value']) }}{{ $safety['compliance']['unit'] }}
{{ $safety['compliance']['delta_label'] }}
Infractions
{{ $fmtNum($safety['infractions']['value']) }}
{{ $safety['infractions']['delta_label'] }}
Alertes actives
{{ $fmtNum($safety['active_alerts']['value']) }}
{{ $safety['active_alerts']['delta_label'] }}
@endsection