@php use App\Support\Money; /** * v3.15.0 §4 — L'activité appels d'offres en un document. * Se rend tel quel sur une base SANS AUCUN AO : zéros, tableaux vides, moyennes à « — ». */ $montant = fn ($v) => $v !== null ? Money::format($v) : '—'; $pourcent = fn (?float $v, bool $signe = false) => $v === null ? '—' : (($signe && $v > 0) ? '+' : '').number_format($v, 1, ',', ' ').' %'; $couleurStatut = [ 'en_preparation' => '#6b7280', 'depose' => '#0EA5E9', 'admissible' => '#2563EB', 'retenu' => '#16A34A', 'ecarte' => '#DC2626', 'annule' => '#6b7280', ]; @endphp @extends('pdf.layout') @section('styles') h2 { font-size: 12px; color: #0F172A; margin: 18px 0 4px; padding-bottom: 3px; border-bottom: 2px solid #F59E0B; } .badge { display: inline-block; padding: 1px 6px; border-radius: 8px; color: #fff; font-size: 8px; font-weight: bold; } .vide { color: #9ca3af; font-size: 10px; padding: 6px 0; } table.data td, table.data th { font-size: 9px; } /* Un montant coupé en deux lignes ne se lit plus : les colonnes chiffrées ne se cassent pas. */ table.data td.num, table.data th.num { white-space: nowrap; } .objet { font-size: 8px; color: #94a3b8; } @endsection @section('content')
Appels d'offres
{{ $kpi['total'] }}
Gagnés
{{ $kpi['won'] }}
Perdus
{{ $kpi['lost'] }}
En préparation
{{ $kpi['preparing'] }}
Taux de réussite
{{ $pourcent($kpi['win_rate']) }}
CA gagné (notre part)
{{ Money::format($kpi['revenue_won']) }}
Offre moyenne (notre part)
{{ $montant($kpi['avg_offer']) }}
Écart moyen / vainqueur
{{ $pourcent($kpi['avg_gap_vs_winner'], true) }}
sur les AO perdus
Concurrents suivis
{{ $kpi['competitors'] }}

Principaux acheteurs

@if ($buyers === [])
Aucun appel d'offres enregistré.
@else @foreach ($buyers as $acheteur) @endforeach
AcheteurAOGagnésOffres cumulées (notre part)
{{ $acheteur['name'] }} {{ $acheteur['tenders'] }} {{ $acheteur['won'] }} {{ Money::format($acheteur['offers']) }}
@endif

Concurrents les plus rencontrés

@if ($competitors === [])
Aucun résultat par concurrent n'est enregistré.
@else @foreach ($competitors as $concurrent) @endforeach
ConcurrentRencontresVictoiresTauxÉcart moyen / estimation
{{ $concurrent['name'] }} {{ $concurrent['tenders'] }} {{ $concurrent['won'] }} {{ number_format($concurrent['win_rate'], 0) }} % {{ $pourcent($concurrent['avg_gap'], true) }}
@endif

Synthèse des appels d'offres

@if ($tenders->isEmpty())
Aucun appel d'offres enregistré.
@else @foreach ($tenders as $ao) @endforeach
Référence Acheteur Statut Notre offre Retenu Offre gagnante Résultat
{{ $ao->reference ?: '—' }}
{{ \Illuminate\Support\Str::limit((string) $ao->object, 60) }}
{{ $ao->buyer_name ?: '—' }} {{ $ao->status->label() }} {{ $montant($ao->our_offer) }} {{ $ao->winner_name ?: '—' }} {{ $montant($ao->winning_offer) }} {{ $ao->result_date?->format('d/m/Y') ?? '—' }}
@endif @endsection