@php use App\Support\Money; use App\Support\PdfText; use App\Support\SectionsDeLignes; // $stamp et $showWithholding sont fournis par le service de rendu ; // $density par DensitePdf (rendu direct sans densité → confort, l'esprit // du rendu historique). $stamp = $stamp ?? null; $showWithholding = $showWithholding ?? true; $density = $density ?? 'confort'; $aere = $density === 'confort'; $hasVat = $invoice->vat_mode?->avecTva() && (float) $invoice->total_tva > 0; $hasWithholding = (float) $invoice->retenue_source > 0; $objet = PdfText::clean($invoice->objet); $hasPaymentBlock = $invoice->mode_reglement || $invoice->date_echeance || $company['banque'] || $company['rib']; // v1.8.0 §A — préférences d'affichage par pièce (OUI par défaut = rendu // historique) et lignes regroupées en sections consécutives. $showLineNumbers = (bool) ($invoice->show_line_numbers ?? true); $showSectionSubtotals = (bool) ($invoice->show_section_subtotals ?? true); $groupes = SectionsDeLignes::grouper($invoice->lines); $colCount = $showLineNumbers ? 6 : 5; // Un avoir se présente pour ce qu'il est : une pièce de sens inverse. $natureDeLaPiece = $invoice->estAvoir() ? 'AVOIR' : 'FACTURE'; // Assemblées en PHP plutôt qu'enchaînées en directives collées : voir // l'explication du piège dans pdf/document-footer.blade.php. $mentionsEmetteur = collect([ $company['ice'] ? 'ICE : '.$company['ice'] : null, $company['if'] ? 'IF : '.$company['if'] : null, ])->filter()->implode(' · '); @endphp @include('pdf.document-styles') {{-- Marqueur de la densité retenue (testable sur le HTML rendu). --}} {{-- (A) En-tête : logo et société à gauche, « FACTURE N° 36/2026 » sur une seule ligne à droite, Date (+ Échéance) dessous. --}}
@if ($logo) {{-- Largeur imposée, hauteur libre : logo-pdf.png est un bandeau de 1200 × 376 et non un carré. Le borner par la hauteur le rendait minuscule. --}} @endif
{{ $company['nom'] }}
{{-- Le séparateur ne paraît que si les deux coordonnées existent. --}} {{ collect([$company['telephone'], $company['email']])->filter()->implode(' · ') }} @if ($company['siege'])
{{ $company['siege'] }}@endif
@if ($invoice->aPrisRang())
{{ $natureDeLaPiece }} N° {{ $invoice->numero }}
@else {{-- Un brouillon n'occupe aucun rang : pas de numéro à afficher. --}}
{{ $natureDeLaPiece }} — brouillon
@endif
Date : {{ $invoice->date?->format('d/m/Y') }} @if ($invoice->date_echeance)
Échéance : {{ $invoice->date_echeance->format('d/m/Y') }} @endif
 
{{-- (B) Émetteur / Facturé à --}}
Émetteur
{{ $company['nom'] }}
@if ($company['siege']) {{ $company['siege'] }}
@endif {{ $mentionsEmetteur }}
Facturé à
{{ $invoice->client_nom }}
@if ($invoice->client_adresse) {!! nl2br(e(PdfText::clean($invoice->client_adresse))) !!}
@endif @if ($invoice->client_ice) ICE : {{ $invoice->client_ice }} @endif
{{-- (C) Objet — le bloc références de Mobdie reste le sien. --}} @if ($objet)
Objet : {{ $objet }}
@endif {{-- (D) Tableau des prestations. La colonne N° suit la préférence ; sa largeur revient à la désignation (≥ 58 %, 62 % sans numéros) ; P.U. HT et Total HT à 13 % restent larges pour les plus gros montants. --}} @if ($showLineNumbers) @endif {{-- v1.8.0 §A — lignes regroupées en sections consécutives (bandeau + sous-total HT), numérotation continue. Sans section, le rendu est identique à avant. --}} @php $i = 0; @endphp @foreach ($groupes as $groupe) @if ($groupe['title'] !== null) @endif @foreach ($groupe['lines'] as $line) @if ($showLineNumbers) @endif @php $i++; @endphp @endforeach {{-- Sous-total masquable par pièce ; le bandeau de section reste. --}} @if ($groupe['title'] !== null && $showSectionSubtotals) @endif @endforeach
N°Désignation Qté Unité P.U. HT Total HT
{{ PdfText::clean($groupe['title']) }}
{{ $i + 1 }}{!! nl2br(e(PdfText::clean($line->designation))) !!} {{ Money::quantite($line->quantite) }} {{ $line->unite ?: 'U' }} {{ Money::format($line->prix_unitaire_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
TOTAL HORS TAXE{{ Money::format($invoice->total_ht, false) }}
TVA{{ Money::format($invoice->total_tva, false) }}
TOTAL TTC EN DIRHAMS{{ Money::format($invoice->total_ttc + $invoice->retenue_source, false) }}
Retenue à la source ({{ Money::taux($invoice->retenue_source_taux) }}) − {{ Money::format($invoice->retenue_source, false) }}
NET À ENCAISSER{{ Money::format($invoice->total_ttc, false) }}
{{-- (F) Montant en toutes lettres --}}
Arrêtée la présente facture à la somme de {{ $montantLettres }}@if ($hasWithholding) (net à encaisser)@endif.
{{-- (G) Règlement + (H) une seule case : celle de l'émetteur. La case « Réception du client — Date, cachet et signature » qui figurait à droite n'avait rien à faire sur une facture. On signe un devis, on accepte une commande ; une facture ne se signe pas, elle constate une créance déjà née. La case laissait croire au client qu'il pouvait la refuser en ne signant pas. Elle reste sur le devis, où elle a un sens : c'est là que l'accord se donne. L'avoir suit la facture — il la corrige, il ne se négocie pas. v1.8.0 §B — le cadre est élargi à ~49 % et porte la hauteur d'un tampon encreur physique (voir .sign dans la feuille de style). --}} @if ($hasPaymentBlock) @else @endif
Règlement
@if ($invoice->mode_reglement)Mode de règlement : {{ $invoice->mode_reglement }}
@endif @if ($invoice->date_echeance)Échéance : {{ $invoice->date_echeance->format('d/m/Y') }}
@endif @if ($company['banque'])Banque : {{ $company['banque'] }}
@endif @if ($company['rib'])RIB : {{ $company['rib'] }}@endif
Cachet et signature de l'émetteur
@if ($stamp) Cachet @endif
{{-- (I) Pied de page légal, 2 lignes, répété au bas de chaque page --}} @include('pdf.document-footer', ['company' => $company])