@php use App\Support\Money; use App\Support\PdfText; use App\Enums\InvoiceVatMode; // $showWithholding et $stamp sont fournis par le contrôleur. $showWithholding = $showWithholding ?? true; $stamp = $stamp ?? null; $hasVat = $quote->vat_mode === InvoiceVatMode::Tva20; $hasWithholding = (float) $quote->vat_withheld > 0; $hasIsWithholding = (float) $quote->is_withheld > 0; $logo = \App\Support\Identite::cheminLogo(); $qty = static fn ($q): string => rtrim(rtrim(number_format((float) $q, 2, ',', ' '), '0'), ','); $rate = static fn ($r): string => rtrim(rtrim(number_format((float) $r, 2, ',', ' '), '0'), ','); // Normalisation des champs texte pour ne jamais afficher de « ? ». $object = PdfText::clean($quote->object); $marketReference = PdfText::clean($quote->market_reference); $tenderReference = PdfText::clean($quote->tender_reference); $hasRefBlock = $marketReference || $tenderReference || $object || $quote->valid_until; $hasPaymentBlock = $company['bank_name'] || $company['rib']; // v3.14.0 §B — mêmes préférences d'affichage que la facture (OUI par défaut). $showLineNumbers = (bool) ($quote->show_line_numbers ?? true); $showSectionSubtotals = (bool) ($quote->show_section_subtotals ?? true); // La colonne Unité se masque si aucune ligne n'en a ; la colonne N° suit la préférence. $showUnitColumn = $quote->lines->contains(fn ($l): bool => filled($l->unit)); $colCount = ($showUnitColumn ? 6 : 5) - ($showLineNumbers ? 0 : 1); // v3.14.0 §B — mêmes deux préréglages de densité que la facture, choisis par DensitePdf // (mesure du rendu réel). Rendu direct de la vue sans densité → compact. $density = $density ?? 'compact'; $aere = $density === 'confort'; @endphp {{-- v3.14.0 §B — marqueur de la densité retenue (testable sur le HTML rendu). --}} {{-- (A) En-tête clair : logo + société à gauche, DEVIS N° à droite --}} {{-- Le numéro rejoint la ligne DEVIS ; dessous : Date (+ Validité). --}}
@if ($logo !== null) @endif
{{ $company['name'] }}
@if ($company['phone']){{ $company['phone'] }}@endif @if ($company['email']) · {{ $company['email'] }}@endif @if ($company['address'])
{{ $company['address'] }}@endif
DEVIS N° {{ $quote->number }}
Date : {{ $quote->date?->format('d/m/Y') }} @if ($quote->valid_until)
Valable jusqu'au : {{ $quote->valid_until->format('d/m/Y') }}@endif
 
{{-- (B) Émetteur / Devis pour --}}
Émetteur
{{ $company['name'] }}
@if ($company['address']){{ $company['address'] }}
@endif @if ($company['ice'])ICE : {{ $company['ice'] }}@endif @if ($company['if']) · IF : {{ $company['if'] }}@endif
Devis pour
{{ $quote->client_name }}
@if ($quote->client_address){!! nl2br(e($quote->client_address)) !!}
@endif @if ($quote->client_ice)ICE : {{ $quote->client_ice }}@endif
{{-- (C) Référence marché + N° AO + Objet + validité (v3.14.0 §B — comme la facture) --}} @if ($hasRefBlock) @php $refLines = []; if ($marketReference) { $refLines[] = 'Réf. marché : '.e($marketReference); } if ($tenderReference) { $refLines[] = 'N° AO : '.e($tenderReference); } if ($object) { $refLines[] = 'Objet : '.e($object); } if ($quote->valid_until) { $refLines[] = 'Devis valable jusqu\'au '.e($quote->valid_until->format('d/m/Y')).'.'; } @endphp
{!! implode('
', $refLines) !!}
@endif {{-- (D) Tableau des prestations --}} {{-- Mêmes largeurs que la facture : désignation ≥ 58 % (62 % sans numéros). --}} @if ($showLineNumbers) @endif @if ($showUnitColumn) @else @endif {{-- v3.13.0 §B — même logique de sections que la facture (bandeau + sous-total HT), numérotation continue. Sans section, le rendu est identique à avant. --}} @php $groupes = \App\Support\SectionsDeLignes::grouper($quote->lines); $i = 0; @endphp @foreach ($groupes as $groupe) @if ($groupe['title'] !== null) @endif @foreach ($groupe['lines'] as $line) @if ($showLineNumbers) @endif @if ($showUnitColumn) @endif @php $i++; @endphp @endforeach {{-- v3.14.0 §B — sous-total masquable par devis ; le bandeau de section reste. --}} @if ($groupe['title'] !== null && $showSectionSubtotals) @endif @endforeach
N°Désignation Qté UnitéDésignation QtéPU HT Total HT
{{ PdfText::clean($groupe['title']) }}
{{ $i + 1 }}{!! nl2br(e(PdfText::clean($line->designation))) !!} {{ $qty($line->quantity) }}{{ $line->unit }}{{ Money::format($line->unit_price_ht, false) }} {{ Money::format($line->total_ht, false) }}
Sous-total HT - {{ PdfText::clean($groupe['title']) }}{{ Money::format($groupe['subtotal'], false) }}
{{-- (E) Totaux --}} @if ($hasVat) @endif @if ($showWithholding && $hasWithholding) @endif @if ($showWithholding && $hasIsWithholding) @endif @if ($showWithholding && ($hasWithholding || $hasIsWithholding)) @endif
TOTAL HORS TAXE{{ Money::format($quote->total_ht, false) }}
TVA à {{ $rate($quote->vat_rate) }}%{{ Money::format($quote->total_vat, false) }}
TOTAL TTC EN DHS{{ Money::format($quote->total_ttc, false) }}
Retenue TVA à la source ({{ $rate($quote->vat_withholding_rate) }}%)− {{ Money::format($quote->vat_withheld, false) }}
Retenue à la source IS ({{ $rate($quote->is_withholding_rate) }}%)− {{ Money::format($quote->is_withheld, false) }}
NET À PAYER{{ Money::format($quote->net_payable, false) }}
{{-- (F) Montant en toutes lettres --}}
Arrêté le présent devis à la somme de {{ $amountInWords }}@if ($amountInWordsIsNet) (net à payer)@endif.
{{-- (G) Coordonnées bancaires --}} @if ($hasPaymentBlock)
Coordonnées bancaires
@if ($company['bank_name'])Banque : {{ $company['bank_name'] }}
@endif @if ($company['rib'])RIB : {{ $company['rib'] }}@endif
@endif {{-- (H) Deux cases distinctes : cachet prestataire (notre cachet, centré) / bon pour accord client --}}
Cachet et signature du prestataire
@if ($stamp && is_file($stamp)) Cachet @endif @if (($signature ?? null) && is_file($signature)) Signature @endif
Bon pour accord — client
Date et signature du client
{{-- (I) Pied de page fixe (répété en bas de chaque page) — 2 lignes maximum. --}}