@php use App\Support\Money; /** * v3.15.0 §3 — Tout ce qu'on sait d'un concurrent : ses indicateurs, les tendances déduites * (jamais recalculées ici : elles viennent de CompetitorInsightService) et l'historique complet * de ses soumissions, avec le face-à-face de nos propres offres. */ $montant = fn ($v) => $v !== null ? Money::format($v) : '—'; $pourcent = fn (?float $v) => $v === null ? '—' : ($v > 0 ? '+' : '').number_format($v, 1, ',', ' ').' %'; @endphp @extends('pdf.layout') @section('styles') h2 { font-size: 12px; color: #0F172A; margin: 18px 0 4px; padding-bottom: 3px; border-bottom: 2px solid #F59E0B; } table.fiche { width: 100%; border-collapse: collapse; } table.fiche th { width: 22%; text-align: left; vertical-align: top; padding: 5px 6px; font-size: 10px; color: #475569; background: #F8FAFC; border-bottom: 1px solid #e5e7eb; font-weight: normal; } table.fiche td { padding: 5px 6px; font-size: 10px; border-bottom: 1px solid #e5e7eb; vertical-align: top; } .tendances { border-left: 4px solid #F59E0B; background: #F8FAFC; padding: 7px 10px; font-size: 10px; margin-top: 8px; } .tendances ul { margin: 4px 0 0 14px; padding: 0; } .pastille { display: inline-block; padding: 0 5px; border-radius: 7px; font-size: 8px; background: #E2E8F0; color: #475569; } tr.gagnee td { background: #FEF3C7; } .gagne-nous { color: #16A34A; font-weight: bold; } .vide { color: #9ca3af; font-size: 10px; padding: 6px 0; } .objet { font-size: 8px; color: #94a3b8; } /* 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; } @endsection @section('content')

Identité

@if (filled($competitor->notes)) @endif
Raison sociale {{ $competitor->name }} ICE {{ $competitor->ice ?: '—' }}
Notes{{ $competitor->notes }}

Indicateurs

AO rencontrés
{{ $stats['tenders'] }}
Retenu
{{ $stats['retained'] }}
Écarté
{{ $stats['eliminated'] }}
Taux de réussite
{{ number_format($stats['win_rate'], 0) }} %
Écart moyen / estimation
{{ $pourcent($stats['avg_gap_reference']) }}
@if ($stats['insights'] !== [])
Tendances
@endif
Éliminations par étape @if ($stats['eliminations_by_stage'] === []) — @else @foreach ($stats['eliminations_by_stage'] as $etape => $nombre) {{ \App\Enums\EliminationStage::from($etape)->label() }} : {{ $nombre }}  @endforeach @endif

Historique des soumissions

@if ($history === [])
Aucune soumission enregistrée pour ce concurrent.
@else @foreach ($history as $ligne) @endforeach
Appel d'offres Date Son offre Rang Issue Face à face
{{ $ligne['reference'] }} — {{ $ligne['buyer'] }}
{{ \Illuminate\Support\Str::limit($ligne['object'], 70) }}
{{ $ligne['date']?->format('d/m/Y') ?? '—' }} {{ $montant($ligne['offer']) }} {{ $ligne['rank'] ?? '—' }} @if ($ligne['retained']) Retenu @elseif ($ligne['eliminated']) Écarté @if ($ligne['stage'] !== null){{ $ligne['stage']->label() }}@endif @else Admissible @endif @if ($ligne['we_won']) {{ $nousMemes }} retenue @elseif ($ligne['our_offer'] !== null) {{ Money::format($ligne['our_offer']) }} @if ($ligne['gap_our_offer'] !== null) {{ $pourcent($ligne['gap_our_offer']) }} @endif @else — @endif
Face à face : notre offre sur le même appel d'offres — l'écart en pastille est celui de SON offre par rapport à la nôtre (positif = plus cher que nous).
@endif @endsection