Ajout du type Intérêt plateforme pour les remboursements

This commit is contained in:
ocroguennec committed 2026-08-16 16:49:20 +02:00
1 parent 37f9f8b8a7
commit 1bab97b5b3
9 files changed
+248 -66

No files matched your search

@@ -15,7 +15,7 @@ import { fmtEUR } from '../utils/format.js';
* en dessous, et se ferme au scroll/resize (repositionnement non géré en direct, comme InvSelect).
*
* Props :
* value : '' | 'BONUS_PARRAINAGE' | 'BONUS_PLATEFORME' | id (string/number)
* value : '' | 'BONUS_PARRAINAGE' | 'BONUS_PLATEFORME' | 'INTERETS_PLATEFORME' | id (string/number)
* onChange : (value) => void
* options : investissementOptions — { id, plateforme_nom, nom_projet, montant_investi }[]
*/
@@ -29,6 +29,7 @@ export default function InvestissementSelect({ value, onChange, options = [] })
const selectedOption = options.find(i => String(i.id) === String(value));
const label = value === 'BONUS_PARRAINAGE' ? '🎁 Bonus Parrainage'
: value === 'BONUS_PLATEFORME' ? '🏆 Bonus Plateforme'
: value === 'INTERETS_PLATEFORME' ? '🏦 Intérêts plateforme'
: selectedOption ? `${selectedOption.plateforme_nom} — ${selectedOption.nom_projet} (${fmtEUR(selectedOption.montant_investi)})`
: null;
@@ -123,6 +124,7 @@ export default function InvestissementSelect({ value, onChange, options = [] })
<button type="button" style={rowStyle(value === '')} onClick={() => select('')}>—</button>
<button type="button" style={rowStyle(value === 'BONUS_PARRAINAGE')} onClick={() => select('BONUS_PARRAINAGE')}>🎁 Bonus Parrainage</button>
<button type="button" style={rowStyle(value === 'BONUS_PLATEFORME')} onClick={() => select('BONUS_PLATEFORME')}>🏆 Bonus Plateforme</button>
<button type="button" style={rowStyle(value === 'INTERETS_PLATEFORME')} onClick={() => select('INTERETS_PLATEFORME')}>🏦 Intérêts plateforme</button>
<div className="cat-select-sep" />
{options.map(i => (
<button key={i.id} type="button" style={rowStyle(String(value) === String(i.id))} onClick={() => select(String(i.id))}>
+11 -6
View File
@@ -38,6 +38,7 @@ export const MOUV_TYPE_LABELS = {
remboursement: 'Remboursement', bonus: 'Bonus', cashback: 'Cashback', souscription: 'Souscription',
prelevement_ir: 'Prélèvement IR', prelevement_csg: 'Prélèvement CSG',
prelevement_local: "Prélèvement impôts à l'étranger",
interets_plateforme: 'Intérêts plateforme',
};
export function mouvToCSV(rows) {
@@ -147,7 +148,8 @@ export function DetailPanel({ row, onEdit, onDeleteCorrection, onViewRemb, onVie
const isCorrection = row.type === 'correction';
const isBonus = row.type === 'bonus';
const isCashback = row.type === 'cashback';
const isRemb = row.type === 'remboursement' || isBonus || isCashback;
const isInteretsPlateforme = row.type === 'interets_plateforme';
const isRemb = row.type === 'remboursement' || isBonus || isCashback || isInteretsPlateforme;
const isSouscription = row.type === 'souscription';
const isPrelevement = row.type === 'prelevement_ir' || row.type === 'prelevement_csg' || row.type === 'prelevement_local';
const isAuto = row.source === 'auto_remboursement';
@@ -156,6 +158,7 @@ export function DetailPanel({ row, onEdit, onDeleteCorrection, onViewRemb, onVie
: isBonus ? 'Bonus'
: isCashback ? 'Cashback'
: row.type === 'remboursement' ? 'Remboursement (porte-monnaie, brut)'
: isInteretsPlateforme ? 'Intérêts plateforme (porte-monnaie, brut)'
: row.type === 'prelevement_ir' ? 'Prélèvement impôt sur le revenu'
: row.type === 'prelevement_csg' ? 'Prélèvement CSG'
: row.type === 'prelevement_local' ? "Prélèvement impôts à l'étranger"
@@ -173,7 +176,7 @@ export function DetailPanel({ row, onEdit, onDeleteCorrection, onViewRemb, onVie
const montantFmt = `${sign} ${fmtEUR(Math.abs(row.montant))}`;
const montantColor = undefined;
const isRembOnly = row.type === 'remboursement';
const isRembOnly = row.type === 'remboursement' || isInteretsPlateforme;
const fields = [
{ label: 'Plateforme', value: row.plateforme_nom },
@@ -182,7 +185,7 @@ export function DetailPanel({ row, onEdit, onDeleteCorrection, onViewRemb, onVie
{ label: 'Date', value: fmtDate(row.date_operation) },
isRembOnly && row.libelle && { label: 'Projet', value: row.libelle },
(isBonus || isCashback) && row.libelle && { label: 'Projet', value: row.libelle },
isRembOnly && { label: 'Capital', value: fmtEUR(row._capital) },
isRembOnly && !isInteretsPlateforme && { label: 'Capital', value: fmtEUR(row._capital) },
isRembOnly && row._cashback > 0 && { label: 'Cashback', value: fmtEUR(row._cashback) },
isRembOnly && { label: 'Intérêts bruts', value: fmtEUR(row._interets_bruts) },
isRembOnly && { label: 'Traitement fiscal', value: row._isFlatTax
@@ -243,9 +246,11 @@ export function DetailPanel({ row, onEdit, onDeleteCorrection, onViewRemb, onVie
? 'Bonus crédité directement au porte-monnaie de la plateforme.'
: isCashback
? "Cashback crédité au porte-monnaie de la plateforme, saisi sur un remboursement classique plutôt qu'en tant que bonus. Modifiable depuis la page Remboursements."
: row._isAutoSweep
? "Remboursement (montant brut) crédité sur le porte-monnaie puis reversé aussitôt sur le compte courant (retrait automatique associé). Les prélèvements éventuels apparaissent en lignes séparées. Modifiable depuis la page Remboursements."
: "Montant brut du remboursement versé sur le porte-monnaie de la plateforme (méthode « portefeuille ») — les prélèvements éventuels apparaissent en lignes séparées. Modifiable depuis la page Remboursements."}
: isInteretsPlateforme
? "Intérêts versés par la plateforme, hors investissement précis — crédités au porte-monnaie (montant brut). Les prélèvements éventuels apparaissent en lignes séparées. Modifiable depuis la page Remboursements."
: row._isAutoSweep
? "Remboursement (montant brut) crédité sur le porte-monnaie puis reversé aussitôt sur le compte courant (retrait automatique associé). Les prélèvements éventuels apparaissent en lignes séparées. Modifiable depuis la page Remboursements."
: "Montant brut du remboursement versé sur le porte-monnaie de la plateforme (méthode « portefeuille ») — les prélèvements éventuels apparaissent en lignes séparées. Modifiable depuis la page Remboursements."}
</span>
</div>
)}
+41 -27
View File
@@ -20,6 +20,7 @@ const getRatesForYear = (dateStr, pfuRates) => {
};
const BONUS_VALUES = ['BONUS_PARRAINAGE', 'BONUS_PLATEFORME'];
const INTERETS_PLATEFORME_VALUE = 'INTERETS_PLATEFORME';
/**
* RembFormModal — formulaire partagé de saisie/édition d'un remboursement.
@@ -67,6 +68,9 @@ export default function RembFormModal({
confirmingDelete, setConfirmingDelete,
}) {
const isBonus = !locked && BONUS_VALUES.includes(form.investissement_id);
const isInteretsPlateforme = !locked && form.investissement_id === INTERETS_PLATEFORME_VALUE;
// Modes "plateforme" (pas d'investissement précis) : bonus classique ou intérêts plateforme
const isPlateformeMode = isBonus || isInteretsPlateforme;
const rates = getRatesForYear(form.date_remb, pfuRates);
const labelPS = `Prélèvements sociaux${rates ? ` (${fmtRate(rates.prelev_sociaux)})` : ''} (€)`;
@@ -75,8 +79,10 @@ export default function RembFormModal({
const currentInv = locked
? investissements[0]
: (!isBonus ? investissements.find(i => i.id === Number(form.investissement_id)) : null);
const currentPlat = currentInv ? plateformes.find(p => p.id === currentInv.plateforme_id) : null;
: (!isPlateformeMode ? investissements.find(i => i.id === Number(form.investissement_id)) : null);
const currentPlat = isInteretsPlateforme
? plateformes.find(p => String(p.id) === String(form.bonus_plateforme_id))
: (currentInv ? plateformes.find(p => p.id === currentInv.plateforme_id) : null);
const hasLocalTax = !isBonus && currentPlat?.fiscalite === 'avec_fiscalite_locale' && currentPlat?.taux_fiscalite_locale;
const isExonere = !isBonus && currentInv?.fiscalite_override === 'exonere';
const isIndicatif = Boolean(isExonere || (!isBonus && currentPlat && currentPlat.fiscalite !== 'flat_tax'));
@@ -127,7 +133,7 @@ export default function RembFormModal({
{/* ── Sélecteur d'investissement (mode non verrouillé uniquement) ── */}
{!locked && (
<div style={{ gridColumn: isBonus ? 'span 1' : 'span 3' }}>
<div style={{ gridColumn: isPlateformeMode ? 'span 1' : 'span 3' }}>
<label>Investissement *</label>
<InvestissementSelect
value={form.investissement_id}
@@ -136,7 +142,7 @@ export default function RembFormModal({
/>
</div>
)}
{!locked && isBonus && (
{!locked && isPlateformeMode && (
<div>
<label>Plateforme associée</label>
<select value={form.bonus_plateforme_id} onChange={e => {
@@ -156,7 +162,7 @@ export default function RembFormModal({
</div>
)}
{/* ── Champs remboursement normal ── */}
{/* ── Champs remboursement normal / intérêts plateforme ── */}
{!isBonus && (<>
<div style={{ gridColumn: 'span 3', borderTop: '1px solid var(--border)', paddingTop: 4, marginTop: 4 }}>
<span style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em', color: 'var(--text-muted)' }}>Remboursement</span>
@@ -175,11 +181,13 @@ export default function RembFormModal({
onChange={e => onFieldChange('taxe_locale', e.target.value)} />
</div>
)}
<div>
<label>Capital (€)</label>
<input type="number" step="0.01" value={form.capital ?? 0}
onChange={e => onFieldChange('capital', e.target.value)} />
</div>
{!isInteretsPlateforme && (
<div>
<label>Capital (€)</label>
<input type="number" step="0.01" value={form.capital ?? 0}
onChange={e => onFieldChange('capital', e.target.value)} />
</div>
)}
<div>
<label>{hasLocalTax ? 'Intérêts bruts après retenue locale (€)' : 'Intérêts bruts (€)'}</label>
<input type="number" step="0.01" value={form.interets_bruts ?? 0}
@@ -187,11 +195,13 @@ export default function RembFormModal({
style={hasLocalTax ? { background: 'var(--surface-2)', color: 'var(--text-muted)', cursor: 'not-allowed' } : undefined}
onChange={e => !hasLocalTax && onFieldChange('interets_bruts', e.target.value)} />
</div>
<div>
<label>Cashback (€)</label>
<input type="number" step="0.01" value={form.cashback ?? 0}
onChange={e => onFieldChange('cashback', e.target.value)} />
</div>
{!isInteretsPlateforme && (
<div>
<label>Cashback (€)</label>
<input type="number" step="0.01" value={form.cashback ?? 0}
onChange={e => onFieldChange('cashback', e.target.value)} />
</div>
)}
<div style={{ gridColumn: 'span 3', borderTop: '1px solid var(--border)', paddingTop: 4, marginTop: 4 }}>
<span style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em', color: 'var(--text-muted)' }}>Imposition{isIndicatif ? ' — indicatif' : ''}</span>
</div>
@@ -228,16 +238,18 @@ export default function RembFormModal({
<input type="date" required value={form.date_remb || ''}
onChange={e => onFieldChange('date_remb', e.target.value)} />
</div>
{!isInteretsPlateforme && (
<div>
<label>Méthode de remboursement</label>
<select value={form.methode_remboursement || 'portefeuille'}
onChange={e => handleMethodeChange(e.target.value)}>
<option value="portefeuille">Porte-monnaie de la plateforme</option>
<option value="compte_courant">Compte courant de l'investisseur</option>
</select>
</div>
)}
<div>
<label>Méthode de remboursement</label>
<select value={form.methode_remboursement || 'portefeuille'}
onChange={e => handleMethodeChange(e.target.value)}>
<option value="portefeuille">Porte-monnaie de la plateforme</option>
<option value="compte_courant">Compte courant de l'investisseur</option>
</select>
</div>
<div>
{form.methode_remboursement === 'compte_courant' && (
{!isInteretsPlateforme && form.methode_remboursement === 'compte_courant' && (
<>
<label>Compte de réception</label>
{comptesInvestisseur?.length > 0 ? (
@@ -276,10 +288,12 @@ export default function RembFormModal({
onChange={e => onFieldChange('cashback', e.target.value)} />
</div>
)}
{!locked && isBonus && (
<div style={{ gridColumn: 'span 2' }}>
{!locked && isPlateformeMode && (
<div style={{ gridColumn: isBonus ? 'span 2' : 'span 3' }}>
<label>Projet / Commentaire</label>
<input type="text" placeholder="Nom du projet sollicité par le filleul…" value={form.notes || ''}
<input type="text"
placeholder={isBonus ? 'Nom du projet sollicité par le filleul…' : 'Commentaire…'}
value={form.notes || ''}
onChange={e => onFieldChange('notes', e.target.value)} />
</div>
)}
+10 -5
View File
@@ -268,6 +268,7 @@ export default function DepotsRetraits() {
const out = [];
for (const r of allRemb) {
const isBonus = r.type === 'bonus_parrainage' || r.type === 'bonus_plateforme';
const isInteretsPlateforme = r.type === 'interets_plateforme';
const plat = plats.find(p => p.id === r.plateforme_id);
const base = {
_rembId: r.id,
@@ -305,7 +306,7 @@ export default function DepotsRetraits() {
out.push({
...base,
id: `remb_${r.id}`,
type: 'remboursement',
type: isInteretsPlateforme ? 'interets_plateforme' : 'remboursement',
montant: grossMontant,
_isFlatTax: isFlatTax,
_isAutoSweep: r.methode_remboursement === 'compte_courant',
@@ -1140,6 +1141,7 @@ export default function DepotsRetraits() {
<option value="remboursement">Remboursements</option>
<option value="bonus">Bonus</option>
<option value="cashback">Cashback</option>
<option value="interets_plateforme">Intérêts plateforme</option>
<option value="souscription">Souscriptions</option>
<option value="prelevement_ir">Prélèvements IR</option>
<option value="prelevement_csg">Prélèvements CSG</option>
@@ -1251,9 +1253,10 @@ export default function DepotsRetraits() {
</tr>
);
}
if (r.type === 'remboursement' || r.type === 'bonus' || r.type === 'cashback') {
if (r.type === 'remboursement' || r.type === 'bonus' || r.type === 'cashback' || r.type === 'interets_plateforme') {
const isBonus = r.type === 'bonus';
const isCashback = r.type === 'cashback';
const isInteretsPlateforme = r.type === 'interets_plateforme';
return (
<tr key={r.id}
className={`dr-row${selectedRow?.id === r.id ? ' dr-row-selected' : ''}`}
@@ -1269,9 +1272,11 @@ export default function DepotsRetraits() {
padding: '2px 7px', borderRadius: 4,
background: (isBonus || isCashback)
? 'color-mix(in srgb, var(--warning) 18%, transparent)'
: 'color-mix(in srgb, var(--success) 15%, transparent)',
color: (isBonus || isCashback) ? 'var(--warning)' : 'var(--success)',
}}>{isBonus ? 'bonus' : isCashback ? 'cashback' : 'remboursement'}</span>
: isInteretsPlateforme
? 'color-mix(in srgb, var(--primary) 18%, transparent)'
: 'color-mix(in srgb, var(--success) 15%, transparent)',
color: (isBonus || isCashback) ? 'var(--warning)' : isInteretsPlateforme ? 'var(--primary)' : 'var(--success)',
}}>{isBonus ? 'bonus' : isCashback ? 'cashback' : isInteretsPlateforme ? 'intérêts plateforme' : 'remboursement'}</span>
</td>
<td className="text-muted">{r._projet || '—'}</td>
<td className="num success">
+12 -5
View File
@@ -850,6 +850,8 @@ export default function Plateformes() {
: (r.capital || 0) + (r.cashback || 0) + (r.interets_bruts || 0);
} else if (r.type === 'bonus_parrainage' || r.type === 'bonus_plateforme') {
balance += r.cashback || 0;
} else if (r.type === 'interets_plateforme') {
balance += r.net_recu || 0;
}
}
for (const inv of allRows) {
@@ -964,6 +966,7 @@ export default function Plateformes() {
const out = [];
for (const r of allRembs) {
const isBonus = r.type === 'bonus_parrainage' || r.type === 'bonus_plateforme';
const isInteretsPlateforme = r.type === 'interets_plateforme';
const plat = plats.find(p => p.id === r.plateforme_id);
const base = {
_rembId: r.id,
@@ -999,7 +1002,7 @@ export default function Plateformes() {
out.push({
...base,
id: `remb_${r.id}`,
type: 'remboursement',
type: isInteretsPlateforme ? 'interets_plateforme' : 'remboursement',
montant: grossMontant,
_isFlatTax: isFlatTax,
_isAutoSweep: r.methode_remboursement === 'compte_courant',
@@ -2406,6 +2409,7 @@ export default function Plateformes() {
<option value="remboursement">Remboursements</option>
<option value="bonus">Bonus</option>
<option value="cashback">Cashback</option>
<option value="interets_plateforme">Intérêts plateforme</option>
<option value="souscription">Souscriptions</option>
<option value="prelevement_ir">Prélèvements IR</option>
<option value="prelevement_csg">Prélèvements CSG</option>
@@ -2493,9 +2497,10 @@ export default function Plateformes() {
</tr>
);
}
if (r.type === 'remboursement' || r.type === 'bonus' || r.type === 'cashback') {
if (r.type === 'remboursement' || r.type === 'bonus' || r.type === 'cashback' || r.type === 'interets_plateforme') {
const isBonus = r.type === 'bonus';
const isCashback = r.type === 'cashback';
const isInteretsPlateforme = r.type === 'interets_plateforme';
return (
<tr key={r.id}
className={`dr-row${mvSelectedRow?.id === r.id ? ' dr-row-selected' : ''}`}
@@ -2511,9 +2516,11 @@ export default function Plateformes() {
padding: '2px 7px', borderRadius: 4,
background: (isBonus || isCashback)
? 'color-mix(in srgb, var(--warning) 18%, transparent)'
: 'color-mix(in srgb, var(--success) 15%, transparent)',
color: (isBonus || isCashback) ? 'var(--warning)' : 'var(--success)',
}}>{isBonus ? 'bonus' : isCashback ? 'cashback' : 'remboursement'}</span>
: isInteretsPlateforme
? 'color-mix(in srgb, var(--primary) 18%, transparent)'
: 'color-mix(in srgb, var(--success) 15%, transparent)',
color: (isBonus || isCashback) ? 'var(--warning)' : isInteretsPlateforme ? 'var(--primary)' : 'var(--success)',
}}>{isBonus ? 'bonus' : isCashback ? 'cashback' : isInteretsPlateforme ? 'intérêts plateforme' : 'remboursement'}</span>
</td>
<td className="text-muted">{r._projet || '—'}</td>
<td className="num success">
+39 -12
View File
@@ -48,6 +48,7 @@ function TrendBadge({ current, prev, invert = false }) {
const BONUS_VALUES = ['BONUS_PARRAINAGE', 'BONUS_PLATEFORME'];
const INTERETS_PLATEFORME_VALUE = 'INTERETS_PLATEFORME';
const ICONS_BASE = '/api/icons-files/';
const BONUS_TYPE_MAP = { BONUS_PARRAINAGE: 'bonus_parrainage', BONUS_PLATEFORME: 'bonus_plateforme' };
@@ -424,9 +425,9 @@ export default function Remboursements() {
if (tableFilter.type && tableFilter.type !== 'correction_solde' && r.type !== tableFilter.type) return false;
if (tableFilter.type === 'correction_solde') return false; // géré séparément
// Filtre projet
const isBonusTypeFilter = tableFilter.type === 'bonus_parrainage' || tableFilter.type === 'bonus_plateforme';
const isBonusTypeFilter = tableFilter.type === 'bonus_parrainage' || tableFilter.type === 'bonus_plateforme' || tableFilter.type === 'interets_plateforme';
if (!isBonusTypeFilter && tableFilter.investissement_id) {
const isBonus = r.type === 'bonus_parrainage' || r.type === 'bonus_plateforme';
const isBonus = r.type === 'bonus_parrainage' || r.type === 'bonus_plateforme' || r.type === 'interets_plateforme';
if (isBonus) return false;
if (String(r.investissement_id) !== String(tableFilter.investissement_id)) return false;
}
@@ -535,9 +536,13 @@ export default function Remboursements() {
const openEdit = (r) => {
setEditingId(r.id);
const isBonus = r.type === 'bonus_parrainage' || r.type === 'bonus_plateforme';
const sentinelle = r.type === 'bonus_parrainage' ? 'BONUS_PARRAINAGE' : r.type === 'bonus_plateforme' ? 'BONUS_PLATEFORME' : '';
const isInteretsPlateforme = r.type === 'interets_plateforme';
const sentinelle = r.type === 'bonus_parrainage' ? 'BONUS_PARRAINAGE'
: r.type === 'bonus_plateforme' ? 'BONUS_PLATEFORME'
: isInteretsPlateforme ? INTERETS_PLATEFORME_VALUE
: '';
setForm({
investissement_id: isBonus ? sentinelle : r.investissement_id,
investissement_id: (isBonus || isInteretsPlateforme) ? sentinelle : r.investissement_id,
date_remb: r.date_remb,
capital: r.capital, cashback: r.cashback || 0,
interets_bruts_avant_local: r.interets_bruts_avant_local || 0,
@@ -552,7 +557,7 @@ export default function Remboursements() {
});
setErr(null); setModalOpen(true);
// Charge les comptes du détenteur pour le dropdown Compte de réception
if (!isBonus) {
if (!isBonus && !isInteretsPlateforme) {
const invForEdit = investissements.find(i => i.id === r.investissement_id);
if (invForEdit?.investisseur_id) {
api.get(`/investissements/comptes-par-investisseur/${invForEdit.investisseur_id}`)
@@ -654,8 +659,12 @@ export default function Remboursements() {
// Fiscalité locale : calcule taxe_locale et interets_bruts à partir du brut avant retenue
if (k === 'interets_bruts_avant_local') {
const inv = investissements.find(i => i.id === Number(next.investissement_id));
const plat = plateformes.find(p => p.id === inv?.plateforme_id);
const plat = next.investissement_id === INTERETS_PLATEFORME_VALUE
? plateformes.find(p => String(p.id) === String(next.bonus_plateforme_id))
: (() => {
const inv = investissements.find(i => i.id === Number(next.investissement_id));
return plateformes.find(p => p.id === inv?.plateforme_id);
})();
const taux = plat?.fiscalite === 'avec_fiscalite_locale' ? (plat?.taux_fiscalite_locale || 0) : 0;
next.taxe_locale = round2(Number(v) * taux / 100);
next.interets_bruts = round2(Number(v) - next.taxe_locale);
@@ -676,7 +685,7 @@ export default function Remboursements() {
}
// Quand l'investissement change, on hérite silencieusement de la méthode de la plateforme
// (si fermée) ou on remet le défaut (si ouverte, l'utilisateur choisira dans le formulaire)
if (k === 'investissement_id' && !BONUS_VALUES.includes(v)) {
if (k === 'investissement_id' && !BONUS_VALUES.includes(v) && v !== INTERETS_PLATEFORME_VALUE) {
const inv = investissements.find(i => i.id === Number(v));
const plat = plateformes.find(p => p.id === inv?.plateforme_id);
if (plat && plat.methode_remboursement !== 'choix_investisseur') {
@@ -708,6 +717,7 @@ export default function Remboursements() {
};
const isBonus = BONUS_VALUES.includes(form.investissement_id);
const isInteretsPlateforme = form.investissement_id === INTERETS_PLATEFORME_VALUE;
const submit = async (e) => {
e?.preventDefault?.();
@@ -724,6 +734,20 @@ export default function Remboursements() {
statut: form.statut,
notes: form.notes || undefined,
};
} else if (isInteretsPlateforme) {
payload = {
type: 'interets_plateforme',
bonus_plateforme_id: Number(form.bonus_plateforme_id),
bonus_investisseur_id: form.bonus_investisseur_id ? Number(form.bonus_investisseur_id) : undefined,
date_remb: form.date_remb,
interets_bruts_avant_local: Number(form.interets_bruts_avant_local || 0),
taxe_locale: Number(form.taxe_locale || 0),
interets_bruts: Number(form.interets_bruts || 0),
prelev_sociaux: Number(form.prelev_sociaux || 0),
prelev_forfaitaire: Number(form.prelev_forfaitaire || 0),
statut: form.statut,
notes: form.notes || undefined,
};
} else {
payload = {
type: 'normal',
@@ -1136,6 +1160,7 @@ export default function Remboursements() {
<option value="normal">Remboursements</option>
<option value="bonus_parrainage">Bonus Parrainage</option>
<option value="bonus_plateforme">Bonus Plateforme</option>
<option value="interets_plateforme">Intérêts plateforme</option>
<option value="correction_solde">Corrections de solde</option>
</select>
</div>
@@ -1186,6 +1211,8 @@ export default function Remboursements() {
)}
{pagedTableRows.map(r => {
const isBonus = r.type === 'bonus_parrainage' || r.type === 'bonus_plateforme';
const isInteretsPlateforme = r.type === 'interets_plateforme';
const isBonusLike = isBonus || isInteretsPlateforme;
const isCorrection = r._is_correction === true;
const rowKey = isCorrection ? `corr-${r.id}` : `remb-${r.id}`;
return (
@@ -1214,7 +1241,7 @@ export default function Remboursements() {
<td>
{isCorrection
? <span style={{ color: 'var(--text-muted)', fontStyle: 'italic' }}>{r.nom_projet}</span>
: isBonus
: isBonusLike
? <span style={{ color: 'var(--text-muted)', fontStyle: 'italic' }}>{r.nom_projet}</span>
: r.nom_projet}
</td>
@@ -1233,9 +1260,9 @@ export default function Remboursements() {
<span className="text-muted">Porte-monnaie</span>
)}
</td>
<td className="num">{(isBonus || isCorrection) ? '—' : fmtEUR(r.capital)}</td>
<td className="num" style={{ color: !isBonus && !isCorrection && r.capital_restant_du <= 0 ? 'var(--success)' : undefined }}>
{(isBonus || isCorrection) ? '—' : fmtEUR(Math.max(0, r.capital_restant_du ?? 0))}
<td className="num">{(isBonusLike || isCorrection) ? '—' : fmtEUR(r.capital)}</td>
<td className="num" style={{ color: !isBonusLike && !isCorrection && r.capital_restant_du <= 0 ? 'var(--success)' : undefined }}>
{(isBonusLike || isCorrection) ? '—' : fmtEUR(Math.max(0, r.capital_restant_du ?? 0))}
</td>
<td className="num">{r.cashback ? fmtEUR(r.cashback) : '—'}</td>
<td className="num">{(isBonus || isCorrection) ? '—' : fmtEUR(r.interets_bruts)}</td>