facturation: correction

This commit is contained in:
maximus
2026-07-12 16:25:53 +02:00
parent eb48f506cf
commit 9ad44d57b3
2 changed files with 11 additions and 11 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>GISE Nexus | Portail d'Infrastructure Centralisée</title> <title>NEXUS by gise | Portail d'Infrastructure Centralisée</title>
<meta name="description" content="Accédez au portail GISE Nexus. Pilotez votre hébergement web, vos instances serveurs et votre stockage Cloud depuis une console unifiée."> <meta name="description" content="Accédez au portail GISE Nexus. Pilotez votre hébergement web, vos instances serveurs et votre stockage Cloud depuis une console unifiée.">
</head> </head>
<body> <body>
+10 -10
View File
@@ -9,7 +9,7 @@ export default function BillingHistory() {
const [error, setError] = useState(null); const [error, setError] = useState(null);
const [customAlert, setCustomAlert] = useState(null); const [customAlert, setCustomAlert] = useState(null);
// 🎯 NOUVEL ÉTAT : La facture actuellement ouverte dans la modale // NOUVEL ÉTAT : La facture actuellement ouverte dans la modale
const [selectedInvoice, setSelectedInvoice] = useState(null); const [selectedInvoice, setSelectedInvoice] = useState(null);
const triggerAlert = (title, message, type) => { const triggerAlert = (title, message, type) => {
@@ -26,7 +26,6 @@ export default function BillingHistory() {
throw new Error("Impossible de vérifier votre identité ou session expirée."); throw new Error("Impossible de vérifier votre identité ou session expirée.");
} }
const invoicesData = await getInvoicesHistory(profileData.id); const invoicesData = await getInvoicesHistory(profileData.id);
// On s'assure de bien cibler le tableau (correction précédente)
setInvoices(invoicesData.data || []); setInvoices(invoicesData.data || []);
} catch (err) { } catch (err) {
setError(err.message || "Problème de connexion avec le serveur."); setError(err.message || "Problème de connexion avec le serveur.");
@@ -43,12 +42,14 @@ export default function BillingHistory() {
switch (status?.toLowerCase()) { switch (status?.toLowerCase()) {
case 'paid': case 'paid':
if (isNegative) {
return { label: 'REMBOURSÉE', css: 'bg-blue-500/10 text-blue-400 border-blue-500/20', icon: <RefreshCcw className="w-3.5 h-3.5" /> };
}
return { label: 'PAYÉE', css: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20', icon: <CheckCircle2 className="w-3.5 h-3.5" /> }; return { label: 'PAYÉE', css: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20', icon: <CheckCircle2 className="w-3.5 h-3.5" /> };
case 'refunded': case 'refunded':
// 🎯 NOUVEAU STATUT : REMBOURSÉE // NOUVEAU STATUT : REMBOURSÉE
return { label: 'REMBOURSÉE', css: 'bg-blue-500/10 text-blue-400 border-blue-500/20', icon: <RefreshCcw className="w-3.5 h-3.5" /> };
case 'unpaid': case 'unpaid':
// 🎯 SI IMPAYÉE MAIS NÉGATIVE = EN COURS DE TRAITEMENT // SI IMPAYÉE MAIS NÉGATIVE = EN COURS DE TRAITEMENT
if (isNegative) { if (isNegative) {
return { label: 'REMBOURSEMENT EN COURS', css: 'bg-amber-500/10 text-amber-400 border-amber-500/20', icon: <Clock className="w-3.5 h-3.5" /> }; return { label: 'REMBOURSEMENT EN COURS', css: 'bg-amber-500/10 text-amber-400 border-amber-500/20', icon: <Clock className="w-3.5 h-3.5" /> };
} }
@@ -118,7 +119,7 @@ export default function BillingHistory() {
</thead> </thead>
<tbody className="divide-y divide-gray-800/40 text-sm"> <tbody className="divide-y divide-gray-800/40 text-sm">
{invoices.map((invoice) => { {invoices.map((invoice) => {
const badge = getStatusBadge(invoice.status); const badge = getStatusBadge(invoice.status, invoice.total);
return ( return (
<tr key={invoice.id} className="hover:bg-gray-800/20 transition-colors"> <tr key={invoice.id} className="hover:bg-gray-800/20 transition-colors">
<td className="py-5 px-6 font-mono text-xs font-bold text-gray-300"> <td className="py-5 px-6 font-mono text-xs font-bold text-gray-300">
@@ -168,8 +169,7 @@ export default function BillingHistory() {
)} )}
{/* ========================================== */} {/* ========================================== */}
{/* 🌟 LA MODALE DE DÉTAILS DE FACTURE */} {/* LA MODALE DE DÉTAILS DE FACTURE */}
{/* ========================================== */}
{selectedInvoice && ( {selectedInvoice && (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/80 backdrop-blur-sm"> <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/80 backdrop-blur-sm">
<div className="bg-[#090f1c] border border-gray-800 shadow-2xl shadow-cyan-500/10 rounded-2xl w-full max-w-2xl flex flex-col max-h-[90vh] overflow-hidden"> <div className="bg-[#090f1c] border border-gray-800 shadow-2xl shadow-cyan-500/10 rounded-2xl w-full max-w-2xl flex flex-col max-h-[90vh] overflow-hidden">
@@ -211,7 +211,7 @@ export default function BillingHistory() {
<h4 className="text-xs font-bold text-gray-500 uppercase tracking-widest mb-3 border-b border-gray-800 pb-2">Détail des prestations</h4> <h4 className="text-xs font-bold text-gray-500 uppercase tracking-widest mb-3 border-b border-gray-800 pb-2">Détail des prestations</h4>
<div className="space-y-4"> <div className="space-y-4">
{(() => { {(() => {
// 🎯 FILTRE : On ne garde que les items dont le prix est strictement supérieur à 0 // FILTRE : On ne garde que les items dont le prix est strictement supérieur à 0
const validItems = selectedInvoice.items const validItems = selectedInvoice.items
? selectedInvoice.items.filter(item => parseFloat(item.price) > 0) ? selectedInvoice.items.filter(item => parseFloat(item.price) > 0)
: []; : [];
@@ -246,7 +246,7 @@ export default function BillingHistory() {
</div> </div>
</div> </div>
{/* 🧠 CALCULS MATHÉMATIQUES (EXTRACTION TVA DEPUIS LE TTC) */} {/* CALCULS (EXTRACTION TVA DEPUIS LE TTC) */}
{(() => { {(() => {
// Le total récupéré de la BDD est considéré comme le PRIX FINAL (TTC) // Le total récupéré de la BDD est considéré comme le PRIX FINAL (TTC)
const totalTTC = parseFloat(selectedInvoice.total) || 0; const totalTTC = parseFloat(selectedInvoice.total) || 0;