@php $champ = 'mt-1 block h-11 w-full rounded-xl border-gray-300 text-base shadow-sm dark:border-white/20 dark:bg-white/5 dark:text-white'; $etiquette = 'block text-xs font-semibold uppercase text-gray-500 dark:text-gray-400'; $pct = fn (float $v): string => rtrim(rtrim(number_format($v, 1, ',', ' '), '0'), ',').' %'; @endphp {{-- v4.4.0 §C2 → v4.8.0 §E — « PRIMES » : un seul écran, trois onglets. Mensuelles : bandeau (mois, clôture, repères) → « Comment un mois se calcule » (les points du MOIS AFFICHÉ, lus des paramètres figés) → tableau, une ligne par collaborateur, avec LE CALCUL EN FRANÇAIS → pied d'actions (dont le panneau « Missions de renfort »). Commerciales : les primes de l'ancien système et leurs règles — les mêmes données. Réglages : un lien-carte, pas un double formulaire. ⚠️ Tri par NOM, jamais par montant : un tableau trié par prime est un classement. --}} {{-- ═══ Les onglets ══════════════════════════════════════════════════════════════════ --}}
@foreach (['mensuelles' => 'Mensuelles · '.mb_strtolower($moisLisible), 'commerciales' => 'Commerciales', 'reglages' => 'Réglages des primes'] as $cle => $libelle) @endforeach
@if ($onglet === 'mensuelles') {{-- ═══ Bandeau ═══════════════════════════════════════════════════════════════════════ --}}

{{ $moisLisible }}

@if ($reperes['cloture_le']) clôturé le {{ $reperes['cloture_le']->format('d/m/Y') }} · propositions du moteur @else propositions du moteur @endif

{{ $reperes['jours'] }} jours ouvrés {{ $reperes['maximum'] }} pts max {{ $reperes['propositions'] }} proposition{{ $reperes['propositions'] > 1 ? 's' : '' }} {{ \App\Support\Money::format($reperes['total']) }}
{{-- ═══ v4.8.0 §E — « Comment un mois se calcule », avec les points DU MOIS AFFICHÉ ═══ --}}

Comment un mois se calcule

{{ $explication['fige'] ? 'paramètres photographiés pour '.mb_strtolower($moisLisible).' — ils ne bougent plus' : 'paramètres courants — ils seront photographiés au premier calcul du mois' }}

@unless ($explicationRepliee)
@foreach ($explication['gestes'] as $geste)
+{{ $geste['points'] }} {{ $geste['libelle'] }} {{ $geste['explication'] }}
@endforeach

Chaque soir à {{ str_replace(':', ' h ', $explication['heure_calcul']) }}, {{ $explication['max_jour'] }} pts au maximum. Points du mois ÷ maximum (jours ouvrés × {{ $explication['max_jour'] }}) = taux → sous {{ $pct($explication['seuils'][0] ?? 60) }} : rien @foreach (\App\Enums\NiveauPrime::paliers() as $i => $palier) · {{ $pct($explication['seuils'][$i] ?? 0) }} {{ $palier->label() }} {{ $pct($explication['parts'][$i] ?? 0) }} @endforeach de la cible de chacun (sur sa fiche). Série @foreach ($explication['serie_seuils'] as $i => $seuil) ≥ {{ $seuil }} j : {{ ($explication['serie_points'][$i] ?? 0) > 0 ? '+'.$explication['serie_points'][$i].' pts' : 'badge' }}{{ $loop->last ? '' : ' ·' }} @endforeach ({{ $explication['jokers'] }} joker{{ $explication['jokers'] > 1 ? 's' : '' }}/mois). Objectif d'équipe atteint : +{{ $explication['objectif_equipe'] }} · coup de pouce : +{{ $explication['coup_de_pouce'] }} · part du chef : {{ $pct($explication['part_chef']) }} de sa cible × ponctualité de son équipe · moins de {{ $explication['min_taches'] }} tâches reçues dans le mois : pas de niveau automatique. Le 1ᵉʳ du mois, le moteur propose — vous validez, ajustez ou refusez.

@endunless
{{-- ═══ Le tableau ════════════════════════════════════════════════════════════════════ --}} @if ($lignes->isEmpty())

Aucune proposition — le moteur clôture le 1er du mois.

@else
@foreach ($lignes as $ligne) @php $prime = $ligne['prime']; @endphp {{-- Le détail du calcul, ligne par ligne, avec les paramètres du mois. --}} @if ($detailOuvert === $prime->id) @endif {{-- La feuille de décision, en ligne dans le tableau. --}} @if ($decisionSur === $prime->id) @endif @endforeach
Collaborateur Le calcul, en français Proposé Décision État

{{ $ligne['nom'] }}

{{ $ligne['regime'] }} · cible {{ $ligne['cible'] !== null ? \App\Support\Money::format($ligne['cible']) : '—' }}

{{ $ligne['niveau']->label() }}
{{ $ligne['phrase'] }} @if ($ligne['propose'] !== null) {{ \App\Support\Money::format($ligne['propose']) }} @else à fixer manuellement @endif @if ($prime->status === \App\Enums\BonusStatus::Proposee)
@if ($ligne['propose'] !== null) Valider Ajuster @else Fixer manuellement @endif Refuser
@else {{ $prime->tranche_le?->format('d/m/Y') ?? '—' }} @endif
{{ $prime->status->label() }} @if ($prime->status === \App\Enums\BonusStatus::Due) {{ $prime->pay_with_payroll ? 'avec la paie' : 'par virement' }} @endif @if ($prime->ajuste_motif) {{ $prime->ajuste_motif }} @endif
    @foreach ($ligne['lignes'] as $explicationLigne)
  • • {{ $explicationLigne }}
  • @endforeach

{{ $ligne['points'] }} / {{ $ligne['maximum'] }} pts · {{ $pct($ligne['taux']) }} · Paramètres du mois figés : barème {{ implode(' · ', array_values((array) ($prime->parametresFiges()['bareme'] ?? []))) }} · maximum {{ $prime->parametresFiges()['max_jour'] ?? '—' }} pts/jour · niveaux {{ implode(' / ', array_values((array) ($prime->parametresFiges()['niveaux']['seuils'] ?? []))) }} % ⇒ {{ implode(' / ', array_values((array) ($prime->parametresFiges()['niveaux']['parts'] ?? []))) }} %. Rejouer ce mois redonnera le même montant.

@switch($decision) @case('refuser') Refuser la prime de {{ $ligne['nom'] }} @break @case('manuel') Fixer la prime de {{ $ligne['nom'] }} @break @default Ajuster la prime de {{ $ligne['nom'] }} @endswitch

@if ($decision !== 'refuser')
@endif
Enregistrer Annuler
@endif

Proposée → Due (paie ou virement selon le régime) · Refusée → aucune ligne · tout est journalisé. Une prime non activée sur la fiche d'un collaborateur ne fait aucune ligne : il n'est pas dans le dispositif.

{{-- ═══ Pied d'actions ════════════════════════════════════════════════════════════════ --}}
Valider toutes les propositions{{ $reperes['total'] > 0 ? ' ('.\App\Support\Money::format($reperes['total']).')' : '' }} Coup de pouce Missions de renfort @if ($missionsAValider->isNotEmpty()) {{ $missionsAValider->count() }} à valider @endif Règlement des primes (PDF)
@if ($coupDePouce)

+ Coup de pouce

Le motif est obligatoire, et le plafond mensuel s'applique : le geste garde sa valeur.

Donner Annuler
@endif {{-- v4.8.0 §E — Missions renfort en panneau : la validation existante, sans changer de page. --}} @if ($renfortOuvert)
@if ($missionsAValider->isEmpty())

Aucune mission confirmée en attente de validation.

@else
    @foreach ($missionsAValider as $mission)
  • {{ $mission->motif }}

    {{ $mission->type->label() }} · {{ $mission->quand() }} · {{ $mission->libelleDuMarche() }} · {{ $mission->employee?->full_name ?? '—' }}

    @if ((int) (auth()->user()?->employee_id ?? 0) === (int) $mission->employee_id) on ne valide pas sa propre mission @else {{ $renfortSur === $mission->id ? 'Fermer' : 'Valider / refuser' }} @endif
    @if ($renfortSur === $mission->id)
    Valider Refuser
    @endif
  • @endforeach
@endif
@endif
@endif {{-- ═══ v4.8.0 §E — Commerciales : l'ancien système, rangé là où on le cherche ═══════ --}} @if ($onglet === 'commerciales') Primes commerciales X % du décompte encaissé, montant fixe à la soumission retenue… — les mêmes données que « Primes générées », rangées ici. Rien n'est réécrit. Ouvrir Primes générées › @if ($commerciales->isEmpty())

Aucune prime commerciale générée — elles naissent des règles ci-dessous, à l'encaissement d'un décompte ou à une soumission retenue.

@else
@foreach ($commerciales as $bonus) @endforeach
Bénéficiaire Marché Règle Montant Échéance État
{{ $bonus->beneficiaryName() }} {{ $bonus->project?->libelle() ?? '—' }} {{ $bonus->bonusRule?->readableSummary() ?? '—' }} {{ \App\Support\Money::format((float) $bonus->amount) }} {{ $bonus->due_date?->format('d/m/Y') ?? '—' }} {{ $bonus->status->label() }}
@endif
Règles de primes commerciales ce qui déclenche une prime, sur quelle base, pour qui Ouvrir Règles de primes › @if ($regles->isEmpty())

Aucune règle de prime commerciale.

@else @endif
@endif {{-- ═══ v4.8.0 §E — Réglages : un lien-carte, pas un double formulaire ═══════════════ --}} @if ($onglet === 'reglages') Réglages des primes Le barème du jour, la prime du mois (niveaux, série, joker, minimum de tâches, part du chef), le renfort et les heures sup vivent dans Réglages RH — un seul formulaire, pas deux. Un changement prend effet au 1ᵉʳ du mois suivant : le mois en cours garde sa photographie.
Ouvrir Réglages RH Majorations légales (Réglages paie)

La cible de chacun se règle sur sa fiche (Équipe → Collaborateurs).

@endif