feat: majoration 5% affichee partout (PDF, email, admin, page client)

Entite Echeancier :
- MAJORATION_RATE = 0.05 constante
- getMajoration() : montant de la majoration
- getTotalWithMajoration() : total creance + 5%
- getMonthlyAmount() : calcule sur le total majore

Controller create :
- Echeances calculees sur le total majore (pas le total brut)

PDF EcheancierPdf :
- Bloc resume : creance, majoration (rouge), total a payer
- Tableau total : "TOTAL (creance + majoration 5%)"

Email proposition :
- Lignes creance, majoration +5% (rouge), total a payer

Page process (client) :
- 4 colonnes : creance, majoration 5%, total a payer, mensualite

Admin show :
- Carte "Creance + majoration 5%" avec detail

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-04-08 20:14:11 +02:00
parent 6370b8481f
commit 6fe95b5c42
6 changed files with 62 additions and 16 deletions

View File

@@ -51,7 +51,9 @@ class EcheancierController extends AbstractController
}
$totalHtFloat = (float) str_replace(',', '.', $totalHt);
$monthlyAmount = round($totalHtFloat / $nbEcheances, 2);
$majoration = round($totalHtFloat * Echeancier::MAJORATION_RATE, 2);
$totalMajore = round($totalHtFloat + $majoration, 2);
$monthlyAmount = round($totalMajore / $nbEcheances, 2);
$echeancier = new Echeancier($customer, $description, number_format($totalHtFloat, 2, '.', ''));
@@ -65,7 +67,7 @@ class EcheancierController extends AbstractController
for ($i = 1; $i <= $nbEcheances; ++$i) {
$scheduledAt = $start->modify('+'.($i - 1).' months');
$amount = $i === $nbEcheances
? number_format($totalHtFloat - ($monthlyAmount * ($nbEcheances - 1)), 2, '.', '')
? number_format($totalMajore - ($monthlyAmount * ($nbEcheances - 1)), 2, '.', '')
: number_format($monthlyAmount, 2, '.', '');
$line = new EcheancierLine($echeancier, $i, $amount, $scheduledAt);

View File

@@ -340,8 +340,26 @@ class Echeancier
return $this;
}
public const MAJORATION_RATE = 0.05;
// ── Computed ──
/**
* Montant de la majoration (5% du montant total).
*/
public function getMajoration(): float
{
return round((float) $this->totalAmountHt * self::MAJORATION_RATE, 2);
}
/**
* Montant total avec majoration (total + 5%).
*/
public function getTotalWithMajoration(): float
{
return round((float) $this->totalAmountHt + $this->getMajoration(), 2);
}
public function getNbLines(): int
{
return $this->lines->count();
@@ -391,12 +409,12 @@ class Echeancier
}
/**
* Montant mensuel (total / nb echeances).
* Montant mensuel (total majore / nb echeances).
*/
public function getMonthlyAmount(): float
{
$nb = $this->getNbLines();
return $nb > 0 ? round((float) $this->totalAmountHt / $nb, 2) : 0.0;
return $nb > 0 ? round($this->getTotalWithMajoration() / $nb, 2) : 0.0;
}
}

View File

@@ -128,10 +128,22 @@ class EcheancierPdf extends Fpdi
$labelW = 55;
$this->SetFont('Arial', '', 10);
$this->Cell($labelW, 6, $this->enc('Montant total HT :'), 0, 0, 'L');
$this->Cell($labelW, 6, $this->enc('Montant de la creance :'), 0, 0, 'L');
$this->SetFont('Arial', 'B', 10);
$this->Cell(0, 6, number_format((float) $this->echeancier->getTotalAmountHt(), 2, ',', ' ').' '.EURO, 0, 1, 'L');
$this->SetFont('Arial', '', 10);
$this->Cell($labelW, 6, $this->enc('Majoration (5%) :'), 0, 0, 'L');
$this->SetFont('Arial', 'B', 10);
$this->SetTextColor(220, 38, 38);
$this->Cell(0, 6, '+ '.number_format($this->echeancier->getMajoration(), 2, ',', ' ').' '.EURO, 0, 1, 'L');
$this->SetTextColor(0, 0, 0);
$this->SetFont('Arial', '', 10);
$this->Cell($labelW, 6, $this->enc('Total a payer :'), 0, 0, 'L');
$this->SetFont('Arial', 'B', 11);
$this->Cell(0, 6, number_format($this->echeancier->getTotalWithMajoration(), 2, ',', ' ').' '.EURO, 0, 1, 'L');
$this->SetFont('Arial', '', 10);
$this->Cell($labelW, 6, $this->enc('Nombre d\'echeances :'), 0, 0, 'L');
$this->SetFont('Arial', 'B', 10);
@@ -182,11 +194,11 @@ class EcheancierPdf extends Fpdi
$fill = !$fill;
}
// Total
// Total avec majoration
$this->SetFont('Arial', 'B', 10);
$this->SetFillColor(253, 191, 4);
$this->Cell(70, 8, $this->enc(' TOTAL'), 0, 0, 'L', true);
$this->Cell(50, 8, number_format((float) $this->echeancier->getTotalAmountHt(), 2, ',', ' ').' '.EURO, 0, 0, 'R', true);
$this->Cell(70, 8, $this->enc(' TOTAL (creance + majoration 5%)'), 0, 0, 'L', true);
$this->Cell(50, 8, number_format($this->echeancier->getTotalWithMajoration(), 2, ',', ' ').' '.EURO, 0, 0, 'R', true);
$this->Cell(50, 8, '', 0, 1, 'C', true);
$this->Ln(5);

View File

@@ -39,8 +39,9 @@
{# Resume #}
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
<div class="glass p-4">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Montant total</p>
<p class="text-2xl font-bold mt-1">{{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} &euro;</p>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Creance + majoration 5%</p>
<p class="text-2xl font-bold mt-1">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</p>
<p class="text-[10px] text-gray-400 mt-1">{{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} + <span class="text-red-500 font-bold">{{ echeancier.majoration|number_format(2, ',', ' ') }} &euro;</span></p>
</div>
<div class="glass p-4">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Mensualite</p>

View File

@@ -28,14 +28,19 @@
</div>
{# Resume #}
<div class="grid grid-cols-3 gap-3 mb-6">
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-6">
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Total HT</p>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Creance</p>
<p class="text-lg font-bold mt-1">{{ echeancier.totalAmountHt|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Echeances</p>
<p class="text-lg font-bold mt-1">{{ echeancier.nbLines }} mois</p>
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Majoration 5%</p>
<p class="text-lg font-bold mt-1 text-red-500">+ {{ echeancier.majoration|number_format(2, ',', ' ') }} &euro;</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Total a payer</p>
<p class="text-lg font-bold mt-1">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</p>
<p class="text-[10px] text-gray-400">en {{ echeancier.nbLines }} mois</p>
</div>
<div class="glass p-3 text-center">
<p class="text-[9px] font-bold uppercase tracking-wider text-gray-400">Mensualite</p>

View File

@@ -17,8 +17,16 @@
<td style="padding: 10px 16px; font-size: 13px; font-weight: 700;">{{ echeancier.description }}</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Montant total HT</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700;">{{ echeancier.totalAmountHt }} &euro;</td>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Montant de la creance</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700;">{{ echeancier.totalAmountHt }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Majoration (5%)</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 14px; font-weight: 700; color: #dc2626;">+ {{ echeancier.majoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Total a payer</td>
<td style="padding: 10px 16px; font-family: monospace; font-size: 16px; font-weight: 700;">{{ echeancier.totalWithMajoration|number_format(2, ',', ' ') }} &euro;</td>
</tr>
<tr>
<td style="padding: 10px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #9ca3af; background: #f9fafb;">Nombre d'echeances</td>