test bug in facture
This commit is contained in:
parent
78e75ce41c
commit
a2421c86ee
1 changed files with 100 additions and 59 deletions
|
|
@ -79,7 +79,7 @@ export type StatusCode = keyof typeof FACTURE_STATUS_LABELS;
|
|||
// TYPES
|
||||
// ============================================
|
||||
|
||||
type FilterType = 'all' | 'paid' | 'pending' | 'validated';
|
||||
type FilterType = 'all' | 'paid' | 'pending' | 'validated' | 'partial';
|
||||
|
||||
interface FactureWithReglement extends Facture {
|
||||
statut_reglement: string;
|
||||
|
|
@ -143,63 +143,100 @@ const KPI_CONFIG: KPIConfig[] = [
|
|||
filter: (factures) => factures,
|
||||
tooltip: { content: "Total des factures sur la période.", source: "Ventes > Factures" }
|
||||
},
|
||||
{
|
||||
id: 'pending',
|
||||
title: 'Nombre de Factures',
|
||||
icon: FileText,
|
||||
color: 'orange',
|
||||
getValue: (factures) => factures.length,
|
||||
getSubtitle: (factures) => {
|
||||
const paid = factures.filter(f => f.statut === 4);
|
||||
const paymentRate = factures.length > 0 ? ((paid.length / factures.length) * 100).toFixed(1) : '0';
|
||||
return `${paymentRate}% payées`;
|
||||
},
|
||||
getChange: (factures, value, period, allFactures) => {
|
||||
const previousPeriodFactures = getPreviousPeriodItems(allFactures, period);
|
||||
const countChange = Number(value) - previousPeriodFactures.length;
|
||||
return countChange !== 0 ? `${countChange > 0 ? '+' : ''}${countChange}` : '0';
|
||||
},
|
||||
getTrend: (factures, value, period, allFactures) => {
|
||||
const previousPeriodFactures = getPreviousPeriodItems(allFactures, period);
|
||||
return Number(value) >= previousPeriodFactures.length ? 'up' : 'down';
|
||||
},
|
||||
filter: (factures) => factures.filter(f => f.statut === 1),
|
||||
},
|
||||
{
|
||||
id: 'paid',
|
||||
title: 'Montant Payé',
|
||||
title: 'Payés',
|
||||
icon: CheckCircle,
|
||||
color: 'green',
|
||||
getValue: (factures) => {
|
||||
const paid = factures.filter(f => f.statut === 4);
|
||||
return Math.round(paid.reduce((sum, item) => sum + item.total_ht, 0));
|
||||
const soldees = factures.filter(f => (f as any).statut_display === 6);
|
||||
return Math.round(soldees.reduce((sum, item) => sum + item.total_ttc, 0));
|
||||
},
|
||||
getSubtitle: (factures) => {
|
||||
const paid = factures.filter(f => f.statut === 4);
|
||||
return `${paid.length} facture${paid.length > 1 ? 's' : ''}`;
|
||||
const soldees = factures.filter(f => (f as any).statut_display === 6);
|
||||
return `${soldees.length} facture${soldees.length > 1 ? 's' : ''}`;
|
||||
},
|
||||
getChange: (factures) => {
|
||||
const paid = factures.filter(f => f.statut === 4);
|
||||
return `${paid.length}/${factures.length}`;
|
||||
getChange: (factures, value, period, allFactures) => {
|
||||
const soldees = factures.filter(f => (f as any).statut_display === 6);
|
||||
const totalFacture = factures.length;
|
||||
return totalFacture > 0 ? `${soldees.length}/${totalFacture}` : '0';
|
||||
},
|
||||
getTrend: (factures, value, period, allFactures) => {
|
||||
const previousPeriodFactures = getPreviousPeriodItems(allFactures, period);
|
||||
const previousPaid = previousPeriodFactures.filter(f => f.statut === 4);
|
||||
const previousPaidAmount = previousPaid.reduce((sum, item) => sum + item.total_ht, 0);
|
||||
return Number(value) >= previousPaidAmount ? 'up' : 'down';
|
||||
const previousSoldees = previousPeriodFactures.filter(f => (f as any).statut_display === 6);
|
||||
const previousTotal = previousSoldees.reduce((sum, item) => sum + item.total_ttc, 0);
|
||||
return Number(value) >= previousTotal ? 'up' : 'down';
|
||||
},
|
||||
filter: (factures) => factures.filter(f => f.statut === 4),
|
||||
tooltip: { content: "Montant des factures payées sur la période.", source: "Ventes > Factures" }
|
||||
filter: (factures) => factures.filter(f => (f as any).statut_display === 6),
|
||||
tooltip: { content: "Montant des factures entièrement réglées.", source: "Ventes > Factures" }
|
||||
},
|
||||
{
|
||||
id: 'partial',
|
||||
title: 'Partiellement réglées',
|
||||
icon: AlertTriangle,
|
||||
color: 'orange',
|
||||
getValue: (factures) => {
|
||||
const partielles = factures.filter(f => (f as any).statut_display === 7);
|
||||
return Math.round(partielles.reduce((sum, item) => sum + ((item as any).reste_a_regler || item.total_ttc), 0));
|
||||
},
|
||||
getSubtitle: (factures) => {
|
||||
const partielles = factures.filter(f => (f as any).statut_display === 7);
|
||||
return `${partielles.length} facture${partielles.length > 1 ? 's' : ''}`;
|
||||
},
|
||||
getChange: (factures, value, period, allFactures) => {
|
||||
const partielles = factures.filter(f => (f as any).statut_display === 7);
|
||||
const totalFacture = factures.length;
|
||||
return totalFacture > 0 ? `${partielles.length}/${totalFacture}` : '0';
|
||||
},
|
||||
getTrend: (factures, value, period, allFactures) => {
|
||||
const previousPeriodFactures = getPreviousPeriodItems(allFactures, period);
|
||||
const previousPartielles = previousPeriodFactures.filter(f => (f as any).statut_display === 7);
|
||||
const previousTotal = previousPartielles.reduce((sum, item) => sum + ((item as any).reste_a_regler || item.total_ttc), 0);
|
||||
return Number(value) <= previousTotal ? 'up' : 'down';
|
||||
},
|
||||
filter: (factures) => factures.filter(f => (f as any).statut_display === 7),
|
||||
tooltip: { content: "Montant restant à régler sur les factures partiellement payées.", source: "Ventes > Factures" }
|
||||
},
|
||||
{
|
||||
id: 'pending',
|
||||
title: 'Non réglées',
|
||||
icon: FileText,
|
||||
color: 'red',
|
||||
getValue: (factures) => {
|
||||
// Factures ni soldées (6) ni partiellement payées (7)
|
||||
const nonReglees = factures.filter(f => (f as any).statut_display !== 6 && (f as any).statut_display !== 7);
|
||||
return nonReglees.length;
|
||||
},
|
||||
getSubtitle: (factures) => {
|
||||
const nonReglees = factures.filter(f => (f as any).statut_display !== 6 && (f as any).statut_display !== 7);
|
||||
const totalRestant = nonReglees.reduce((sum, item) => sum + ((item as any).reste_a_regler || item.total_ttc), 0);
|
||||
return `${totalRestant.toLocaleString('fr-FR')}€ à régler`;
|
||||
},
|
||||
getChange: (factures, value, period, allFactures) => {
|
||||
const previousPeriodFactures = getPreviousPeriodItems(allFactures, period);
|
||||
const previousNonReglees = previousPeriodFactures.filter(f => (f as any).statut_display !== 6 && (f as any).statut_display !== 7);
|
||||
return previousNonReglees.length > 0
|
||||
? (((Number(value) - previousNonReglees.length) / previousNonReglees.length) * 100).toFixed(1)
|
||||
: '0';
|
||||
},
|
||||
getTrend: (factures, value, period, allFactures) => {
|
||||
const previousPeriodFactures = getPreviousPeriodItems(allFactures, period);
|
||||
const previousNonReglees = previousPeriodFactures.filter(f => (f as any).statut_display !== 6 && (f as any).statut_display !== 7);
|
||||
// Moins de non réglées = mieux
|
||||
return Number(value) <= previousNonReglees.length ? 'up' : 'down';
|
||||
},
|
||||
filter: (factures) => factures.filter(f => (f as any).statut_display !== 6 && (f as any).statut_display !== 7),
|
||||
tooltip: { content: "Nombre de factures non réglées.", source: "Ventes > Factures" }
|
||||
},
|
||||
{
|
||||
id: 'validated',
|
||||
title: 'Factures Validées',
|
||||
title: 'Validées',
|
||||
icon: CheckCircle,
|
||||
color: 'purple',
|
||||
getValue: (factures) => factures.filter(f => f.valide === 1).length,
|
||||
getSubtitle: (factures) => {
|
||||
const pending = factures.filter(f => f.statut === 1);
|
||||
return `${pending.length} en attente`;
|
||||
const nonValidees = factures.filter(f => f.valide !== 1);
|
||||
return `${nonValidees.length} non validée${nonValidees.length > 1 ? 's' : ''}`;
|
||||
},
|
||||
getChange: (factures) => {
|
||||
const validated = factures.filter(f => f.valide === 1);
|
||||
|
|
@ -211,6 +248,7 @@ const KPI_CONFIG: KPIConfig[] = [
|
|||
return Number(value) >= previousValidated.length ? 'up' : 'down';
|
||||
},
|
||||
filter: (factures) => factures.filter(f => f.valide === 1),
|
||||
tooltip: { content: "Nombre de factures validées.", source: "Ventes > Factures" }
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -356,6 +394,7 @@ const InvoicesPage = () => {
|
|||
});
|
||||
}, [factures, reglementsMap]);
|
||||
|
||||
|
||||
// ============================================
|
||||
// Client actuellement sélectionné
|
||||
// ============================================
|
||||
|
|
@ -376,16 +415,17 @@ const InvoicesPage = () => {
|
|||
// ============================================
|
||||
|
||||
const kpis = useMemo(() => {
|
||||
const periodFilteredFactures = filterItemByPeriod(factures, period, 'date');
|
||||
// Utiliser facturesWithReglement au lieu de factures
|
||||
const periodFilteredFactures = filterItemByPeriod(facturesWithReglement, period, 'date');
|
||||
|
||||
return KPI_CONFIG.map(config => {
|
||||
const value = config.getValue(periodFilteredFactures);
|
||||
return {
|
||||
id: config.id,
|
||||
title: config.title,
|
||||
value: config.id === 'all' || config.id === 'paid' ? `${value.toLocaleString('fr-FR')}€` : value,
|
||||
change: config.getChange(periodFilteredFactures, value, period, factures),
|
||||
trend: config.getTrend(periodFilteredFactures, value, period, factures),
|
||||
value: config.id === 'all' || config.id === 'paid' || config.id === 'partial' ? `${value.toLocaleString('fr-FR')}€` : value,
|
||||
change: config.getChange(periodFilteredFactures, value, period, facturesWithReglement), // aussi ici
|
||||
trend: config.getTrend(periodFilteredFactures, value, period, facturesWithReglement), // et ici
|
||||
icon: config.icon,
|
||||
subtitle: config.getSubtitle(periodFilteredFactures, value),
|
||||
color: config.color,
|
||||
|
|
@ -394,7 +434,7 @@ const InvoicesPage = () => {
|
|||
onClick: () => setActiveFilter(prev => (prev === config.id ? 'all' : config.id)),
|
||||
};
|
||||
});
|
||||
}, [factures, period, activeFilter]);
|
||||
}, [facturesWithReglement, period, activeFilter]);
|
||||
|
||||
// ============================================
|
||||
// Filtrage combiné : Période + KPI + Filtres avancés
|
||||
|
|
@ -429,6 +469,7 @@ const InvoicesPage = () => {
|
|||
return [...result].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
||||
}, [facturesWithReglement, period, activeFilter, activeFilters, clientCommercialMap]);
|
||||
|
||||
|
||||
// ============================================
|
||||
// Factures sélectionnables
|
||||
// ============================================
|
||||
|
|
|
|||
Loading…
Reference in a new issue