@extends('admin.layout') @section('title', __('Découpes des commandes')) @section('content')

@yield('title')

{{-- Les zones (data-zone) : ce que js/sur-place.js remplace apres un geste, sans recharger la page — messages, compteurs, lignes, pagination, pieces jointes. Le reste ne bouge pas. --}}
@if (session('success'))
{{ session('success') }}
@endif @if (session('error'))
{{ session('error') }}
@endif {{-- Un fichier refuse — trop lourd, mauvais format — revient ici : sans ce bloc, le formulaire du modal echouerait sans un mot. --}} @if ($errors->any())
    @foreach ($errors->all() as $error)
  • {{ $error }}
  • @endforeach
@endif
{{-- La liste vient de la base, elle reste juste : seuls le client et la ville manquent, l'api seule les résout. --}} @if ($sansClient && $lignes->total() > 0)
{{ __("L'api ne répond pas : le client et la ville ne peuvent pas être affichés. Le reste de la liste est à jour.") }}
@endif {{-- Recherche côté serveur : elle porte sur toute la table, pas seulement sur la page affichée. Les filtres actifs partent en champs cachés pour ne pas les perdre. --}}
@foreach ($filtres as $champ => $valeur) @endforeach @if ($tri !== '') @endif @foreach ($commandesFiltre as $id) @endforeach
@if ($q !== '') {{ __('Réinitialiser') }} @endif
{{-- Arrive du tableau de bord (sante des donnees) : pas de pastille pour ce filtre, seulement la puce qui dit ce qu'on regarde et permet d'en sortir. --}} @if ($sansLaseriste) @endif {{-- Arrive de la selection de la liste des commandes : la puce dit lesquelles, et celles qui n'ont aucune decoupe ; la croix rend la liste entiere. --}} @if ($commandesFiltre)
{{ __('Commandes de la sélection : :ids', ['ids' => implode(', ', $commandesFiltre)]) }} @if ($commandesSansDecoupe) {{ __('Sans découpe, rien à suivre : :ids', ['ids' => implode(', ', $commandesSansDecoupe)]) }} @endif
@endif
@include('admin.commande_decoupes._filtres')
{{ __(':n découpe(s) posée(s)', ['n' => $lignes->total()]) }} @if ($lignes->lastPage() > 1) — {{ __('page :courante / :total', ['courante' => $lignes->currentPage(), 'total' => $lignes->lastPage()]) }} @endif
@php // Evalue avant le tableau : l'en-tete en depend aussi. La // selection ne sert qu'a poser le suivi d'un lot, elle suit // donc le droit de modifier. $peutModifier = auth()->user()?->can('commande_decoupes.edit'); @endphp
{{-- Une ligne par decoupe, comme l'index des commandes (meme feuille, cmd-table-compacte) : les libelles longs sont coupes, leur texte entier reste au survol. --}} @if ($peutModifier) {{-- Coche de page : elle ne parle que des lignes affichees, jamais de la selection entiere. --}} @endif {{-- Plan du bureau d'etude : colonne a lui, icone PDF, comme sur l'index des commandes. --}} {{-- cmd-col-large : masquees entre 768 et 1400 px, ou quinze colonnes ne tiennent pas. Le laseriste reste dans le filtre, les dates dans la modale d'edition. --}} {{-- Echeance de la commande : ce qui ordonne le tri par echeance. Meme sablier que sur l'index des commandes. --}} {{-- Deux etats : celui de la commande (usine) et celui de la decoupe (laseriste). Les libelles passent a la ligne, sinon ils elargiraient seuls leur colonne. --}} {{-- Un trombone plutot que le mot : l'en-tete elargissait a lui seul une colonne de petits boutons. Le texte masque sert de libelle aux cartes sur telephone (responsive-tables.js). --}} @php // Évalués une fois pour la page plutôt qu'à chaque ligne. $peutVoirCommande = auth()->user()?->can('commandes.view'); // La poubelle d'une ligne posee par erreur : le droit de // l'ajout, comme sous une commande de la liste. $peutRetirer = auth()->user()?->can('commandes.decoupes'); $peutVoirClient = auth()->user()?->can('clients.view'); $peutVoirDevis = auth()->user()?->can('devis.view'); @endphp @forelse ($lignes as $ligne) @php // L'api rend la commande complète : on n'en garde que // ce que la base ne sait pas dire. $commande = ($clients ?? [])[$ligne->commande_id] ?? null; $client = $commande['client'] ?? null; $devis = $commande['devis'] ?? null; // Le nom vient du contact Gestan ; si le contact n'a pas // pu être résolu, le devis porte souvent la même raison // sociale et évite une ligne vide. $nomClient = $client['libelle'] ?? ($devis['raison_sociale'] ?? null); // Gestan n'a pas résolu le contact : plutôt qu'un tiret // sur lequel cliquer, on remet l'identifiant, qui reste // la seule prise pour retrouver la fiche. if (!$nomClient && !empty($ligne->client_id)) { $nomClient = __('Client') . ' ' . $ligne->client_id; } $ville = trim($devis['ville'] ?? ''); @endphp {{-- data-ligne : la ligne qu'un autre poste a changee se surligne quand la liste se relit (js/sur-place.js). --}} @if ($peutModifier) @endif {{-- Le numero, et en exception la priorite de la commande (hors NORMALE), comme sur l'index des commandes. --}} @php $prioriteLibelle = (int) $ligne->priorite !== 1 ? \App\Helpers\CommandeHelper::priorite($ligne->priorite, '') : ''; @endphp {{-- Client : lien vers la fiche Gestan. Sans identifiant ou sans le droit de la consulter, on garde le nom en texte simple plutôt qu'un lien mort. --}} {{-- Ville du chantier, portée par le devis. Zéro n'est pas un numéro : c'est la marque d'une commande sans devis. --}} @php $libelleModele = $ligne->modele ? mb_strtoupper($ligne->modele, 'UTF-8') : '—'; // Comme l'index des commandes : le code RAL seul // dans la cellule, le nom complet dans l'infobulle. $couleurModele = $ligne->couleur ? \App\Helpers\CommandeHelper::couleur($ligne->couleur, '') : ''; $couleurCourte = $ligne->couleur ? \App\Helpers\CommandeHelper::couleurCourte($ligne->couleur, '') : ''; @endphp {{-- 873 lignes sur 1248 n'ont pas de decoupe_id : elles existent quand même, avec leur date et leur lasériste. On les montre plutôt que de les taire. --}} {{-- Echeance de la commande, calculee comme sur l'index des commandes : seulement tant qu'il reste a la fabriquer. --}} {{-- Etat de la commande a l'usine --}} {{-- Etat de la decoupe chez le laseriste --}} {{-- Ce que le fabricant a envoye pour cette ligne-la : photos, plan corrige. Le detail et le depot vivent dans le modal, sous le tableau — une colonne le plus souvent vide n'a pas a porter un formulaire. --}} @empty @endforelse
{{ __('Commande') }} {{ __('Client') }} {{ __('Ville') }}{{ __('Plan') }} {{ __('Modèle') }} {{ __('Découpe') }}{{ __('Lasériste') }} {{ __('Envoi') }} {{ __('Réception') }} {{ __('Échéance') }} {{ __('État de la commande') }} {{ __('État de la découpe') }} {{ __('Pièces jointes') }}
{{ $ligne->commande_id }} @if ($prioriteLibelle !== '') {{ ['URGENT' => 'URG'][$prioriteLibelle] ?? $prioriteLibelle }} @endif @if (!empty($ligne->client_id) && $peutVoirClient) {{ $nomClient ?: '—' }} @else {{ $nomClient ?: '—' }} @endif @if ((int) $ligne->devis_id > 0 && $peutVoirDevis) {{ $ville ?: '—' }} @else {{ $ville ?: '—' }} @endif @if (!empty($ligne->url)) @endif {{ $libelleModele }} @if ($couleurModele) · {{ $couleurCourte }} @endif @if ($ligne->decoupe_nom) @php $nomDecoupe = \App\Helpers\CommandeHelper::nomTraduit(mb_strtoupper($ligne->decoupe_nom, 'UTF-8')); $typeDecoupe = $ligne->decoupe_type ? \App\Helpers\CommandeHelper::decoupeType($ligne->decoupe_type) : ''; @endphp {{ $nomDecoupe }} @if ($typeDecoupe) · {{ $typeDecoupe }} @endif @elseif ($peutModifier) {{-- Reprise de l'ancien logiciel sans son nom. La colonne est trop etroite pour une liste (96 px sur un portable) : le bouton ouvre la fenetre « Modifier » de la ligne, sur son champ Decoupe. --}} @else {{ __('Non précisée') }} @endif {{ \App\Helpers\CommandeHelper::laseriste($ligne->laseriste, '—') }} @if ($ligne->date_envoi) {{ \Carbon\Carbon::parse($ligne->date_envoi)->format('d/m/y') }} @else — @endif @if ($ligne->date_reception) {{ \Carbon\Carbon::parse($ligne->date_reception)->format('d/m/y') }} @else — @endif @php $previsionnelle = \App\Helpers\CommandeHelper::datePrevue( \App\Helpers\CommandeHelper::depart($ligne->commande_created_at, $ligne->commande_lancee_le), $ligne->maconnerie, $ligne->cintrage, $ligne->commande_etat, $ligne->date_entrepot, $ligne->relaquage_envoi, ); $echeance = \App\Helpers\CommandeHelper::echeance($previsionnelle); @endphp @if ($echeance) {{ $echeance['libelle'] }} @else — @endif @php $etatCommande = \App\Helpers\CommandeHelper::etat($ligne->commande_etat, ''); @endphp @if ($etatCommande !== '') {{ $etatCommande }} @else — @endif @php $etatLibelle = \App\Helpers\CommandeHelper::decoupeEtat($ligne->etat, ''); @endphp @if ($etatLibelle !== '') {{ $etatLibelle }} @else — @endif @php $pieces = $documents[$ligne->id] ?? collect(); $nbNotes = count($notes[$ligne->id] ?? []); @endphp {{-- La meme fenetre porte les notes de la ligne : le bouton les compte a cote des fichiers. --}} @if ($peutVoirCommande) @endif {{-- Ouvre la modale d'edition, partagee par toutes les lignes : le bouton lui passe les valeurs de la sienne. --}} @if ($peutModifier) @endif {{-- Retirer une ligne posee par erreur, tant qu'elle est vierge (CommandeDecoupe::suiviCommence) : la meme poubelle que sous une commande de la liste. Envoyee sur place (js/sur-place.js), le toast la remet. --}} @if ($peutRetirer && !\App\Models\CommandeDecoupe::suiviCommence($ligne, $pieces->isNotEmpty(), $nbNotes > 0)) @php $nomRetrait = $ligne->decoupe_nom ? mb_strtoupper($ligne->decoupe_nom, 'UTF-8') : '#' . $ligne->id; @endphp
@csrf @method('DELETE')
@endif
{{ __('Aucune découpe ne correspond à cette recherche.') }}
{{-- Barre de selection, la meme que sur l'index des commandes (js/commandes/selection.js) : fixe en bas, elle apparait des qu'une ligne est cochee, et la selection se vide au changement de page. Sans etiquettes ici : elle ne pose qu'un etat. `data-cle` ne sert plus qu'a effacer l'ancienne pile gardee dans l'onglet. --}} @if ($peutModifier)
{{-- Lasériste, envoi, réception, état : l'ordre des colonnes. Chaque champ est facultatif, seul ce qui est rempli s'applique — un envoi chez un lasériste n'efface pas les états posés ligne par ligne. --}}
@csrf
@endif
{{ $lignes->links() }}
{{-- Un modal par ligne, rendus après le tableau : posés dans une cellule, Bootstrap les place par rapport au tableau et le fond gris déborde. Ils portent ce que la colonne ne peut pas montrer — la liste des pièces jointes, et le formulaire de dépôt. --}}
@foreach ($lignes as $ligne) @php $pieces = $documents[$ligne->id] ?? collect(); @endphp @endforeach
{{-- Edition du suivi d'une ligne : la meme fenetre que sous une commande de la liste et dans la fiche. --}} @include('admin.commande_decoupes._modale-suivi', ['catalogue' => $catalogue])
{{-- Meme feuille que l'index des commandes : pastilles, etiquettes et separateurs sont les memes composants. --}} {{-- « Définir » d'une decoupe sans nom : la fenetre de sa ligne, le curseur deja dans le champ Decoupe. --}} @endsection