990 lines
71 KiB
React
990 lines
71 KiB
React
import { useEffect, useRef, useState } from 'react';
|
||
import { useLocation, useNavigate } from 'react-router-dom';
|
||
import { withDevOverrides } from '../utils/devOverrides.js';
|
||
|
||
/** Nom de fichier à partir de la question (slug, sans accents). */
|
||
function slugify(text) {
|
||
return text
|
||
.toLowerCase()
|
||
.normalize('NFD').replace(new RegExp('[\\u0300-\\u036f]', 'g'), '')
|
||
.replace(/[^a-z0-9]+/g, '-')
|
||
.replace(/^-+|-+$/g, '')
|
||
.slice(0, 60);
|
||
}
|
||
|
||
/* ── Accordéon FAQ ───────────────────────────────────────────── */
|
||
/* `openQuestion`/`setOpenQuestion` sont partagés par toutes les FaqItem d'une
|
||
même page (état remonté dans le composant parent) : une seule question
|
||
ouverte à la fois, ouvrir la suivante referme automatiquement les autres. */
|
||
function FaqItem({ question, children, openQuestion, setOpenQuestion }) {
|
||
const open = openQuestion === question;
|
||
const toggle = () => setOpenQuestion(open ? null : question);
|
||
const [pdfState, setPdfState] = useState('idle'); // idle | generating | error
|
||
const contentRef = useRef(null);
|
||
|
||
const handleDownloadPdf = async () => {
|
||
if (!contentRef.current || pdfState === 'generating') return;
|
||
setPdfState('generating');
|
||
// Insère le titre directement dans le bloc réel (contentRef), le temps de
|
||
// la capture uniquement, puis le retire — évite de le dupliquer en
|
||
// permanence à l'écran tout en réutilisant l'élément réellement rendu
|
||
// (un conteneur hors-écran séparé est capturé vide par html2canvas :
|
||
// sa zone de rendu ne suit pas un élément poussé loin hors du viewport).
|
||
let heading = null;
|
||
try {
|
||
const { default: html2pdf } = await import('html2pdf.js');
|
||
// Fond capturé = fond réel du bloc (var(--surface)) : reste cohérent
|
||
// que le thème actif soit clair ou sombre, plutôt qu'un blanc forcé
|
||
// qui casserait le contraste du texte en mode sombre.
|
||
const bgColor = getComputedStyle(contentRef.current).backgroundColor || '#ffffff';
|
||
|
||
heading = document.createElement('h3');
|
||
heading.textContent = question;
|
||
heading.style.margin = '0 0 12px';
|
||
heading.style.color = 'var(--text)';
|
||
heading.style.fontSize = '1.1rem';
|
||
contentRef.current.insertBefore(heading, contentRef.current.firstChild);
|
||
|
||
await html2pdf()
|
||
.set({
|
||
margin: 28,
|
||
filename: `faq-${slugify(question) || 'crowdlending'}.pdf`,
|
||
image: { type: 'jpeg', quality: 0.95 },
|
||
html2canvas: { scale: 2, useCORS: true, backgroundColor: bgColor },
|
||
jsPDF: { unit: 'pt', format: 'a4', orientation: 'portrait' },
|
||
// 'avoid-all' : ne coupe jamais un élément (image, bloc de code,
|
||
// ligne de tableau…) au milieu — le pousse entièrement sur la page
|
||
// suivante à la place. C'est ce qui manquait avec le moteur HTML
|
||
// interne de jsPDF (doc.html()), qui tranchait au hasard.
|
||
pagebreak: { mode: ['avoid-all', 'css'] },
|
||
})
|
||
.from(contentRef.current)
|
||
.toPdf()
|
||
.get('pdf')
|
||
.then((pdf) => {
|
||
// Numérotation en bas à droite, une fois le nombre total de pages connu.
|
||
const total = pdf.internal.getNumberOfPages();
|
||
for (let i = 1; i <= total; i++) {
|
||
pdf.setPage(i);
|
||
pdf.setFontSize(9);
|
||
pdf.setTextColor(150);
|
||
pdf.text(
|
||
`${i} / ${total}`,
|
||
pdf.internal.pageSize.getWidth() - 28,
|
||
pdf.internal.pageSize.getHeight() - 16,
|
||
{ align: 'right' }
|
||
);
|
||
}
|
||
})
|
||
.save();
|
||
setPdfState('idle');
|
||
} catch (e) {
|
||
console.error('Échec de la génération du PDF :', e);
|
||
setPdfState('error');
|
||
} finally {
|
||
if (heading && heading.parentNode) heading.parentNode.removeChild(heading);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div style={{
|
||
background: 'var(--surface)',
|
||
border: '1px solid var(--border)',
|
||
borderRadius: 10,
|
||
boxShadow: 'var(--shadow)',
|
||
padding: '0 20px',
|
||
marginBottom: 12,
|
||
}}>
|
||
<button
|
||
onClick={toggle}
|
||
style={{
|
||
width: '100%', textAlign: 'left', background: 'none', border: 'none',
|
||
padding: '14px 0', cursor: 'pointer', display: 'flex',
|
||
alignItems: 'center', justifyContent: 'space-between', gap: 12,
|
||
color: 'var(--text)', fontSize: '1.05rem', fontWeight: 600,
|
||
}}
|
||
>
|
||
<span>{question}</span>
|
||
<svg
|
||
width="16" height="16" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"
|
||
style={{ flexShrink: 0, transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .2s' }}
|
||
>
|
||
<polyline points="6 9 12 15 18 9" />
|
||
</svg>
|
||
</button>
|
||
{open && (
|
||
<div style={{
|
||
paddingBottom: 20, color: 'var(--text-muted)',
|
||
fontSize: 'var(--fs-sm)', lineHeight: 1.7,
|
||
}}>
|
||
<div ref={contentRef} style={{ background: 'var(--surface)' }}>
|
||
{children}
|
||
</div>
|
||
|
||
<button
|
||
onClick={handleDownloadPdf}
|
||
disabled={pdfState === 'generating'}
|
||
style={{
|
||
display: 'inline-flex', alignItems: 'center', gap: 6, marginTop: 16,
|
||
padding: '7px 14px', border: '1px solid var(--border)', borderRadius: 8,
|
||
background: 'var(--surface-2)', color: 'var(--text)',
|
||
fontSize: 'var(--fs-sm)', fontWeight: 500,
|
||
cursor: pdfState === 'generating' ? 'default' : 'pointer',
|
||
opacity: pdfState === 'generating' ? 0.6 : 1,
|
||
}}
|
||
>
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}>
|
||
<path d="M12 3v12" />
|
||
<polyline points="7 10 12 15 17 10" />
|
||
<path d="M5 21h14" />
|
||
</svg>
|
||
{pdfState === 'generating' ? 'Génération du PDF…' : 'Télécharger cette FAQ en PDF'}
|
||
</button>
|
||
{pdfState === 'error' && (
|
||
<p style={{ color: 'var(--danger)', fontSize: 'var(--fs-sm)', margin: '8px 0 0' }}>
|
||
La génération du PDF a échoué. Réessayez, ou imprimez la page (Ctrl+P / Cmd+P) et choisissez
|
||
« Enregistrer en PDF ».
|
||
</p>
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
/* ── Titre de section (regroupement thématique de la FAQ) ──────── */
|
||
function FaqSectionTitle({ children, first }) {
|
||
return (
|
||
<h3 style={{
|
||
margin: first ? '0 0 12px' : '32px 0 12px',
|
||
fontSize: '0.8rem', fontWeight: 700, textTransform: 'uppercase',
|
||
letterSpacing: '0.06em', color: 'var(--text-muted)',
|
||
}}>
|
||
{children}
|
||
</h3>
|
||
);
|
||
}
|
||
|
||
/* ── Lien de téléchargement (fichiers statiques dans public/) ──── */
|
||
function DownloadLink({ href, children }) {
|
||
return (
|
||
<a
|
||
href={href}
|
||
download
|
||
style={{
|
||
display: 'inline-flex', alignItems: 'center', gap: 6,
|
||
color: 'var(--primary)', fontSize: 'var(--fs-sm)', fontWeight: 500,
|
||
textDecoration: 'none', margin: '0 0 12px',
|
||
}}
|
||
>
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}>
|
||
<path d="M12 3v12" />
|
||
<polyline points="7 10 12 15 17 10" />
|
||
<path d="M5 21h14" />
|
||
</svg>
|
||
{children}
|
||
</a>
|
||
);
|
||
}
|
||
|
||
/* ── Navigation ─────────────────────────────────────────────── */
|
||
const NAV = [
|
||
{
|
||
id: 'faq',
|
||
label: 'FAQ',
|
||
icon: (
|
||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||
<circle cx="12" cy="12" r="10" />
|
||
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
|
||
<line x1="12" y1="17" x2="12.01" y2="17" />
|
||
</svg>
|
||
),
|
||
},
|
||
];
|
||
|
||
/* ── Page principale ─────────────────────────────────────────── */
|
||
export default function Aide() {
|
||
const { search } = useLocation();
|
||
const navigate = useNavigate();
|
||
const [openQuestion, setOpenQuestion] = useState(null); // question ouverte dans la FAQ (une seule à la fois)
|
||
const [appInfo, setAppInfo] = useState({}); // { appUrl, mcpUrl } — valeurs brutes de la base, telles quelles
|
||
|
||
useEffect(() => {
|
||
fetch('/api/app-info').then(r => r.json()).then(setAppInfo).catch(() => {});
|
||
}, []);
|
||
|
||
// URL MCP annoncée comme « déjà pré-remplie » : doit refléter ce que
|
||
// Mon compte → Serveur MCP affichera réellement, y compris en dev (où
|
||
// cette page-là retombe elle-même sur localhost via withDevOverrides).
|
||
const mcpConfigUrl = withDevOverrides(appInfo).mcpUrl || 'https://mcp.<votre domaine>/mcp';
|
||
|
||
const section = new URLSearchParams(search).get('section') || 'faq';
|
||
const setSection = (s) => navigate(`/aide?section=${s}`, { replace: true });
|
||
|
||
return (
|
||
<div className="account-layout">
|
||
|
||
{/* ── Nav gauche ───────────────────────────────────────── */}
|
||
<aside className="account-sidebar">
|
||
<h1 className="account-title">Centre d'aide</h1>
|
||
{NAV.map(item => (
|
||
<button
|
||
key={item.id}
|
||
className={`account-nav-item${section === item.id ? ' active' : ''}`}
|
||
onClick={() => setSection(item.id)}
|
||
>
|
||
{item.icon}
|
||
{item.label}
|
||
</button>
|
||
))}
|
||
</aside>
|
||
|
||
{/* ── Contenu ──────────────────────────────────────────── */}
|
||
<div className="account-content">
|
||
|
||
{section === 'faq' && (
|
||
<div>
|
||
<h2 style={{ marginTop: 0, marginBottom: 24, fontSize: '1.6rem', fontWeight: 700 }}>Questions fréquentes</h2>
|
||
|
||
<FaqSectionTitle first>Comprendre la plateforme</FaqSectionTitle>
|
||
|
||
<FaqItem question="Comment est calculé le solde du porte-monnaie d'une plateforme ?" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Le solde du porte-monnaie représente les liquidités disponibles sur une plateforme,
|
||
c'est-à-dire l'argent que vous pouvez retirer ou réinvestir. Il est calculé comme suit :
|
||
</p>
|
||
|
||
<div style={{ margin: '12px 0', padding: '12px 16px', background: 'var(--surface-2)', borderRadius: 8, fontFamily: 'monospace', fontSize: 'var(--fs-sm)', color: 'var(--text)', lineHeight: 2 }}>
|
||
Solde = Dépôts<br />
|
||
− Retraits manuels<br />
|
||
+ Remboursements crédités au porte-monnaie<br />
|
||
+ Bonus (parrainage / plateforme)<br />
|
||
− Capital investi (en cours ou remboursé)<br />
|
||
− Frais (déduits à la souscription ou réglés via le porte-monnaie)<br />
|
||
+ Corrections de solde
|
||
</div>
|
||
|
||
<p><strong style={{ color: 'var(--text)' }}>Retraits manuels</strong> — seuls les retraits que vous avez saisis manuellement sont déduits.
|
||
Les retraits générés automatiquement lors d'un remboursement en mode "compte courant" sont exclus,
|
||
car ils ne représentent pas un vrai mouvement de porte-monnaie.</p>
|
||
|
||
<p><strong style={{ color: 'var(--text)' }}>Remboursements crédités au porte-monnaie</strong> — uniquement les remboursements
|
||
dont le mode est "Portefeuille" (et non "Compte courant"). Le montant crédité dépend de la fiscalité
|
||
de la plateforme :</p>
|
||
<ul style={{ margin: '8px 0 8px 16px', paddingLeft: 0 }}>
|
||
<li style={{ marginBottom: 6 }}>
|
||
<strong style={{ color: 'var(--text)' }}>Plateforme française (Flat Tax)</strong> — le porte-monnaie
|
||
reçoit le <em>net reçu</em>, c'est-à-dire le montant après déduction du PFU français (17,2 % de prélèvements
|
||
sociaux + 12,8 % d'impôt sur le revenu), prélevé directement à la source par la plateforme.
|
||
</li>
|
||
<li style={{ marginBottom: 6 }}>
|
||
<strong style={{ color: 'var(--text)' }}>Plateforme hors France (sans fiscalité locale)</strong> — le porte-monnaie
|
||
reçoit le capital remboursé + cashback + intérêts bruts. Le PFU français n'est pas prélevé à la
|
||
source : vous devez le déclarer séparément dans votre déclaration fiscale annuelle.
|
||
</li>
|
||
<li>
|
||
<strong style={{ color: 'var(--text)' }}>Plateforme hors France (avec retenue à la source locale)</strong> — même
|
||
principe que ci-dessus, mais la plateforme a déjà prélevé une taxe locale sur les intérêts. Le
|
||
porte-monnaie reçoit le capital + cashback + intérêts bruts <em>après</em> cette retenue locale.
|
||
Le PFU français reste à déclarer séparément.
|
||
</li>
|
||
</ul>
|
||
|
||
<p><strong style={{ color: 'var(--text)' }}>Capital investi</strong> — le montant que vous avez placé dans des prêts actifs
|
||
(y compris les réinvestissements complémentaires) est soustrait du porte-monnaie, car ces fonds ne sont
|
||
plus disponibles. Ils reviennent progressivement via les remboursements.</p>
|
||
|
||
<p><strong style={{ color: 'var(--text)' }}>Frais</strong> — les frais liés aux investissements (voir la question dédiée
|
||
ci-dessous) réduisent le solde lorsqu'ils sont réglés « à la source » (déduits du versement lors de la
|
||
souscription) ou via le porte-monnaie. Les frais réglés depuis un compte courant du détenteur, ou retenus
|
||
directement sur un remboursement, n'ont aucun impact ici — ils ne transitent jamais par le porte-monnaie de
|
||
la plateforme.</p>
|
||
|
||
<p style={{ marginBottom: 0 }}><strong style={{ color: 'var(--text)' }}>Corrections de solde</strong> — ajustements manuels
|
||
permettant de réconcilier de micro-écarts de calcul (par exemple un arrondi de centimes sur la fiscalité).</p>
|
||
</FaqItem>
|
||
|
||
<FaqItem question="Comment fonctionne le suivi des frais liés aux investissements ?" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Certaines plateformes facturent des frais en dehors des intérêts et prélèvements fiscaux habituels : frais
|
||
d'entrée à la souscription, frais de gestion, frais sur une distribution (retenus ou non sur un
|
||
remboursement), ou autre. Le bloc <em>Frais d'opération</em> de la fiche d'un investissement les recense tous.
|
||
</p>
|
||
|
||
<p>
|
||
Dès qu'au moins un frais a été déclaré sur l'une de vos plateformes, une page <strong style={{ color: 'var(--text)' }}>Frais</strong> dédiée
|
||
apparaît dans le menu de gauche (entre Remboursements et Fiscalité) — après un rechargement de la page qui
|
||
suit cette première déclaration. Elle consolide, tous investissements confondus, le montant total, la
|
||
répartition par catégorie et le détail de chaque opération, avec ajout/modification/suppression directement
|
||
depuis cette vue (plus besoin de passer par la fiche de chaque investissement). Cette page remplace
|
||
l'ancien onglet « Frais » qui se trouvait dans Remboursements.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Où saisir un frais ?</h4>
|
||
<ul style={{ margin: '0 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li><strong style={{ color: 'var(--text)' }}>Frais de souscription</strong> — depuis l'étape « Frais » du
|
||
formulaire de création ou modification de l'investissement. Un seul frais de cette catégorie par
|
||
investissement.</li>
|
||
<li><strong style={{ color: 'var(--text)' }}>Frais de gestion ou autre</strong> — depuis le bouton
|
||
<strong style={{ color: 'var(--text)' }}> + Ajouter</strong> du bloc <em>Frais d'opération</em> sur la fiche
|
||
de l'investissement, ou depuis la page <em>Frais</em> dédiée (avec sélecteur d'investissement).</li>
|
||
<li><strong style={{ color: 'var(--text)' }}>Frais sur distribution</strong> — depuis le champ
|
||
<strong style={{ color: 'var(--text)' }}> Frais</strong> du formulaire d'un remboursement. La ligne est créée et
|
||
synchronisée automatiquement dans le bloc <em>Frais d'opération</em> et dans la page <em>Frais</em> ; elle ne
|
||
peut être modifiée ou supprimée que depuis ce remboursement, pour éviter toute désynchronisation.</li>
|
||
</ul>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Mode de règlement et impact</h4>
|
||
<p>Chaque frais est réglé de l'une des quatre façons suivantes, avec un impact différent :</p>
|
||
<ul style={{ margin: '8px 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li><strong style={{ color: 'var(--text)' }}>Déduit du versement lors de la souscription</strong> — aucune
|
||
ligne de mouvement séparée : le montant est simplement documenté à titre de traçabilité, mais il réduit
|
||
le solde du porte-monnaie (voir la question ci-dessus).</li>
|
||
<li><strong style={{ color: 'var(--text)' }}>Porte-monnaie</strong> — débité du solde disponible sur la
|
||
plateforme, comme un retrait.</li>
|
||
<li><strong style={{ color: 'var(--text)' }}>Débité du compte courant</strong> — réglé depuis un compte
|
||
courant du détenteur (choisi à la saisie), sans aucun impact sur le porte-monnaie de la plateforme.</li>
|
||
<li><strong style={{ color: 'var(--text)' }}>Déduit du remboursement</strong> — retenu directement sur le
|
||
remboursement lié : le montant réduit alors la base imposable et les <em>intérêts nets</em>/<em>net reçu</em>
|
||
de ce remboursement (comportement historique). C'est le seul mode où le frais n'est pas une sortie d'argent
|
||
séparée à suivre par ailleurs.</li>
|
||
</ul>
|
||
|
||
<p>
|
||
Le KPI <strong style={{ color: 'var(--text)' }}>Gain net depuis le début</strong> du tableau de bord déduit
|
||
tous les frais réellement payés, <strong style={{ color: 'var(--text)' }}>sauf</strong> ceux du mode « Déduit
|
||
du remboursement » : ceux-là sont déjà comptés en creux dans les intérêts nets de ce remboursement (le
|
||
retirer une 2ᵉ fois compterait la même dépense deux fois). Les frais « Déduit du versement lors de la
|
||
souscription », « Porte-monnaie » et « Débité du compte courant » sont chacun une vraie sortie d'argent qui
|
||
n'apparaît nulle part ailleurs dans ce total, donc ils sont bien soustraits.
|
||
</p>
|
||
<p style={{ marginBottom: 0 }}>
|
||
Le <strong style={{ color: 'var(--text)' }}>TRI (XIRR) net</strong> d'un investissement suit une règle
|
||
légèrement différente : seuls les frais « Porte-monnaie » et « Compte courant » y sont ajoutés comme sortie
|
||
de trésorerie. Un frais « Déduit du versement lors de la souscription » n'y est pas rajouté séparément car
|
||
il est déjà reflété dans le montant investi (net du frais dès la souscription) qui sert de point de départ
|
||
au calcul — l'ajouter une 2ᵉ fois fausserait le TRI.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
<FaqItem question="Comment mettre en place un réinvestissement automatique des intérêts ?" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Le réinvestissement automatique permet de capitaliser les intérêts perçus après chaque remboursement,
|
||
sans aucune saisie manuelle. Les intérêts sont automatiquement réinjectés dans le capital du prêt,
|
||
ce qui augmente progressivement le montant investi et les intérêts futurs.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Activation</h4>
|
||
<ol style={{ margin: '0 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li>Ouvrez la fiche d'un investissement.</li>
|
||
<li>Cliquez sur le bouton <strong style={{ color: 'var(--text)' }}>⋮</strong> en haut à droite du bloc <em>Informations du projet</em>, puis choisissez <strong style={{ color: 'var(--text)' }}>Réinvestir</strong>.</li>
|
||
<li>Dans la modale, sélectionnez l'onglet <strong style={{ color: 'var(--text)' }}>Automatique</strong>.</li>
|
||
<li>Cliquez sur <strong style={{ color: 'var(--text)' }}>Activer</strong>.</li>
|
||
</ol>
|
||
<p>
|
||
Une fois activé, le bloc <em>Réinvestissements complémentaires</em> apparaît sur la fiche avec
|
||
un badge <strong style={{ color: 'var(--primary)' }}>auto</strong>, même si aucun remboursement
|
||
n'a encore eu lieu.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Quel montant est réinvesti ?</h4>
|
||
<p>Le montant réinvesti après chaque remboursement dépend de la fiscalité de la plateforme :</p>
|
||
<ul style={{ margin: '8px 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li>
|
||
<strong style={{ color: 'var(--text)' }}>Plateforme française (Flat Tax)</strong> — les <em>intérêts nets</em> sont réinvestis
|
||
(après déduction du PFU prélevé à la source). C'est le montant réellement reçu sur votre porte-monnaie.
|
||
</li>
|
||
<li>
|
||
<strong style={{ color: 'var(--text)' }}>Plateforme hors France</strong> — les <em>intérêts bruts</em> sont réinvestis,
|
||
car aucune retenue n'est effectuée à la source. Pensez à provisionner la fiscalité due lors de votre déclaration annuelle.
|
||
</li>
|
||
</ul>
|
||
<p>Si les intérêts d'un remboursement sont nuls (remboursement de capital seul), aucun réinvestissement n'est créé.</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Désactivation</h4>
|
||
<p style={{ marginBottom: 0 }}>
|
||
Pour désactiver le réinvestissement automatique, cliquez sur <strong style={{ color: 'var(--text)' }}>⋮</strong> dans le bloc
|
||
<em> Informations du projet</em> et choisissez <strong style={{ color: 'var(--text)' }}>Désactiver le réinvestissement auto</strong>.
|
||
Les réinvestissements déjà créés sont conservés ; les prochains remboursements n'en génèreront plus.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
<FaqSectionTitle>Fiscalité</FaqSectionTitle>
|
||
|
||
<FaqItem question="Comment la fiscalité fonctionne-t-elle dans Crowdlending ?" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
La page <strong style={{ color: 'var(--text)' }}>Fiscalité</strong> (menu de gauche) reprend, année par année,
|
||
les montants nécessaires pour préparer votre déclaration de revenus. Elle est organisée en cinq onglets,
|
||
chacun correspondant à un formulaire CERFA officiel :
|
||
</p>
|
||
|
||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 'var(--fs-sm)', margin: '0 0 14px' }}>
|
||
<tbody>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2561</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}><strong style={{ color: 'var(--text)' }}>IFU — Imprimé fiscal unique.</strong> Récapitulatif annuel transmis par les plateformes françaises soumises au prélèvement forfaitaire unique (PFU).</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2047</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}><strong style={{ color: 'var(--text)' }}>Revenus encaissés à l'étranger.</strong> Visible dès qu'une ou plusieurs de vos plateformes sont domiciliées hors de France ; détaille les intérêts perçus pays par pays et le crédit d'impôt associé.</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2778-SD</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}><strong style={{ color: 'var(--text)' }}>Prélèvement forfaitaire obligatoire (PFO)</strong>, selon votre situation fiscale — déclaration mensuelle de l'acompte dû sur les intérêts de plateformes étrangères (voir la question suivante).</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2042</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}><strong style={{ color: 'var(--text)' }}>Déclaration des revenus.</strong> La déclaration principale : reprend les cases calculées à partir des trois formulaires ci-dessus (2TT, 2TR, 2BH, 2CK, 2TY).</td>
|
||
</tr>
|
||
<tr>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2042-C PRO</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}><strong style={{ color: 'var(--text)' }}>Intérêts d'emprunts sur une plateforme d'actif numérique (crowdlending sur RWA).</strong> Visible dès qu'une ou plusieurs de vos plateformes sont de type « Prestataire de Services sur Actifs Numériques » (PSAN) — des bénéfices non commerciaux (BNC), en régime micro (case 5HQ), indépendants des trois formulaires ci-dessus.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<p>Le sens de circulation des données est toujours le même :</p>
|
||
<ul style={{ margin: '8px 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li><code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2561</code> et <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2047</code> alimentent directement la <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2042</code>.</li>
|
||
<li>La <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2778-SD</code> (mensuelle) alimente la <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2047</code> (annuelle), qui seule est ensuite reportée sur la 2042 — la 2778-SD n'est qu'un mécanisme d'acompte intermédiaire, jamais une déclaration de substitution à la 2047.</li>
|
||
<li>La <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2042-C PRO</code> fonctionne à part : les intérêts de plateformes PSAN sont des bénéfices non commerciaux (BNC), pas des revenus de capitaux mobiliers — ils ne transitent ni par la 2047, ni par un crédit d'impôt, et ne sont pas repris dans les cases 2TT/2TR/2BH/2CK/2TY de la 2042. Ils se déclarent séparément, directement sur l'imprimé 2042-C PRO (voir la question dédiée ci-dessous).</li>
|
||
</ul>
|
||
<p>
|
||
Un pavé « À quoi correspond chaque CERFA ? », avec un schéma récapitulatif, est affiché directement en haut de
|
||
l'onglet 2047 lorsque vous avez des plateformes étrangères.
|
||
</p>
|
||
|
||
<p style={{ marginBottom: 0 }}>
|
||
<strong style={{ color: 'var(--text)' }}>Important</strong> — ce module est une aide à la préparation de votre
|
||
déclaration, il ne la remplace pas. Vérifiez chaque montant avant de le reporter sur le site des impôts :
|
||
vous restez seul responsable de l'exactitude de votre déclaration fiscale, Crowdlending ne saurait être
|
||
tenu responsable des données déclarées.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
<FaqItem question="Comment savoir si je suis concerné par la déclaration mensuelle sur mes plateformes étrangères ?" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Cette question concerne le formulaire <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2778-SD</code> (prélèvement
|
||
forfaitaire obligatoire, ou PFO). Elle ne se pose que si vous détenez au moins une plateforme domiciliée
|
||
hors de France.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>La règle</h4>
|
||
<p>
|
||
Le PFO s'applique aux personnes physiques fiscalement domiciliées en France dont le <strong style={{ color: 'var(--text)' }}>revenu
|
||
fiscal de référence (RFR)</strong> de l'avant-dernière année est égal ou supérieur à :
|
||
</p>
|
||
<div style={{ display: 'flex', gap: 12, margin: '8px 0 12px', flexWrap: 'wrap' }}>
|
||
<div style={{ padding: '6px 14px', borderRadius: 20, background: 'rgba(99,102,241,0.08)', border: '1px solid rgba(99,102,241,0.2)', fontSize: 'var(--fs-sm)', fontWeight: 600 }}>
|
||
25 000 € — célibataire, divorcé ou veuf
|
||
</div>
|
||
<div style={{ padding: '6px 14px', borderRadius: 20, background: 'rgba(99,102,241,0.08)', border: '1px solid rgba(99,102,241,0.2)', fontSize: 'var(--fs-sm)', fontWeight: 600 }}>
|
||
50 000 € — couple marié ou pacsé
|
||
</div>
|
||
</div>
|
||
<p>
|
||
Votre RFR figure sur votre <strong style={{ color: 'var(--text)' }}>avis d'imposition</strong> de l'année précédente
|
||
(ligne « Revenu fiscal de référence »). En dessous de ces seuils, vous êtes dispensé du PFO — mais les
|
||
prélèvements sociaux restent dus.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Où l'activer dans l'application</h4>
|
||
<ol style={{ margin: '0 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li>Allez dans <strong style={{ color: 'var(--text)' }}>Paramétrage → Ma fiscalité</strong>.</li>
|
||
<li>Dépliez la carte <strong style={{ color: 'var(--text)' }}>« CERFA 2778-SD — Prélèvement Forfaitaire Obligatoire (PFO) pour des revenus de source étrangère »</strong> pour revoir le détail des seuils.</li>
|
||
<li>Activez le bouton si votre situation vous rend redevable du PFO.</li>
|
||
</ol>
|
||
<p>
|
||
Ce réglage est global : une fois activé, l'onglet <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2778-SD</code> apparaît
|
||
dans la page Fiscalité, les cases <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2BH</code> / <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2CK</code> se
|
||
remplissent dans le report 2042, et les lignes de suivi mensuel du PFO (taux, montant à payer, intérêt net)
|
||
s'affichent dans les tableaux « Suivi mensuel » des onglets 2047 et 2778-SD. Si vous le désactivez, ces
|
||
éléments sont masqués car ils ne s'appliquent pas à votre situation.
|
||
</p>
|
||
|
||
<p style={{ marginBottom: 0 }}>
|
||
<strong style={{ color: 'var(--text)' }}>À retenir</strong> — que le PFO s'applique ou non à vous, la déclaration
|
||
annuelle via le CERFA 2047 reste <strong style={{ color: 'var(--text)' }}>obligatoire</strong> dès que vous avez
|
||
perçu des intérêts d'une plateforme étrangère. Ce paramètre reflète votre propre situation fiscale : en cas
|
||
de doute, vérifiez votre avis d'imposition ou consultez un professionnel.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
<FaqItem question="Comment est calculé le crédit d'impôt sur les intérêts perçus d'une plateforme étrangère ?" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Dans l'onglet <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2047</code>, vue
|
||
« Données 2047 », chaque plateforme étrangère est classée automatiquement selon la convention fiscale
|
||
signée entre la France et son pays de domiciliation.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Éligible au crédit d'impôt (cases 233 à 238)</h4>
|
||
<p>
|
||
Le pays a une convention fiscale <strong style={{ color: 'var(--text)' }}>active</strong> et n'impose pas
|
||
l'imposition exclusivement dans le pays de résidence. Le crédit d'impôt (case 237) est égal à l'impôt
|
||
réellement prélevé à l'étranger (case 236), plafonné au taux conventionnel du pays lorsque celui-ci est
|
||
chiffré (case 234) — ou <strong style={{ color: 'var(--text)' }}>non plafonné</strong> pour certains pays dont
|
||
la convention prévoit un crédit égal à l'impôt prélevé sans limite de taux.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Non éligible (case 250)</h4>
|
||
<p>
|
||
Le pays est absent des conventions fiscales référencées, sa convention est suspendue ou caduque, ou elle
|
||
prévoit une imposition exclusivement dans le pays de résidence. Dans ce cas, aucun crédit d'impôt n'est
|
||
calculé.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Sous-totaux par pays</h4>
|
||
<p style={{ marginBottom: 0 }}>
|
||
Le formulaire papier 2047 se remplit <strong style={{ color: 'var(--text)' }}>par pays</strong>, pas par
|
||
plateforme : si plusieurs de vos plateformes sont domiciliées dans le même pays, une ligne « Sous-total »
|
||
apparaît automatiquement sous le groupe pour faciliter le report. Les totaux 8VL et 8PL (report 2042)
|
||
ainsi que les cases 251/252 cumulent l'ensemble de vos plateformes étrangères, arrondis à l'euro comme
|
||
l'exige le formulaire officiel.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
<FaqItem question="Comment sont imposés les intérêts perçus via une plateforme d'actifs numériques (PSAN) ?" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Certaines plateformes de crowdlending prêtent sur des actifs numériques plutôt que sur des projets
|
||
classiques (crowdlending sur RWA — <em>Real World Asset</em> tokenisés). Dans le référentiel
|
||
Crowdlending, elles sont identifiées par la catégorie <strong style={{ color: 'var(--text)' }}>« Prestataire
|
||
de Services sur Actifs Numériques »</strong> (PSAN), par opposition aux plateformes de financement
|
||
participatif classiques (« Prestataire de Services de Financement Participatif », PSFP).
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Un régime fiscal différent</h4>
|
||
<p>
|
||
Les intérêts perçus via une plateforme PSAN ne sont pas des revenus de capitaux mobiliers (RCM)
|
||
comme les autres — ce sont des <strong style={{ color: 'var(--text)' }}>bénéfices non commerciaux
|
||
(BNC)</strong>, quelle que soit la localisation de la plateforme (française ou étrangère).
|
||
Conséquence directe :
|
||
</p>
|
||
<ul style={{ margin: '8px 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li>Pas de déclaration <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2047</code>, même si la plateforme est domiciliée hors de France.</li>
|
||
<li>Pas de crédit d'impôt conventionnel possible.</li>
|
||
<li>Déclaration directe sur l'imprimé <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2042-C PRO</code>, en régime micro-BNC, case <strong style={{ color: 'var(--text)' }}>5HQ</strong>.</li>
|
||
</ul>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Le régime micro-BNC</h4>
|
||
<p>
|
||
Vous déclarez le montant brut des intérêts reçus (valorisés en euros au jour de leur réception) ;
|
||
l'abattement forfaitaire de <strong style={{ color: 'var(--text)' }}>34 %</strong> est appliqué
|
||
automatiquement par l'administration fiscale, vous n'avez rien à calculer vous-même. Si vos
|
||
recettes brutes dépassent <strong style={{ color: 'var(--text)' }}>77 700 €</strong> sur l'année —
|
||
ou si vous souhaitez déduire des charges réelles (matériel, électricité…) — vous basculez en
|
||
régime réel (cases 5KO / 5KP), non géré par l'application.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Dans l'application</h4>
|
||
<p style={{ marginBottom: 0 }}>
|
||
Dès qu'au moins une de vos plateformes est catégorisée PSAN, un onglet <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>CERFA
|
||
2042 C PRO</code> apparaît sur la page Fiscalité, avec un suivi mensuel des intérêts bruts et la
|
||
case 5HQ à reporter — ainsi qu'un bloc dédié « Cases fiscales 2042 C PRO » affiché à côté du
|
||
récapitulatif principal. Vous pouvez vérifier ou modifier la catégorie d'une plateforme (PSFP /
|
||
PSAN) depuis <strong style={{ color: 'var(--text)' }}>Paramétrage → Plateformes</strong>.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
<FaqItem question="Comment utiliser les onglets de la page Fiscalité pour remplir ma déclaration ?" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Chaque onglet CERFA propose généralement plusieurs vues : un <strong style={{ color: 'var(--text)' }}>suivi
|
||
mensuel</strong> (le détail plateforme par plateforme, mois par mois), une vue <strong style={{ color: 'var(--text)' }}>« Données »</strong> (les
|
||
cases du formulaire lui-même), et une vue <strong style={{ color: 'var(--text)' }}>« Report 2042 »</strong> (ce
|
||
qui doit être reporté sur la déclaration principale). Exception : l'onglet <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2042-C PRO</code> ne
|
||
propose que les deux premières vues (Suivi mensuel / Données 2042 C PRO) — il n'existe pas de
|
||
report vers la 2042 classique, les BNC se déclarant sur un imprimé séparé (voir la question dédiée
|
||
aux plateformes PSAN ci-dessus).
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Ordre suggéré</h4>
|
||
<ol style={{ margin: '0 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li>Sélectionnez l'<strong style={{ color: 'var(--text)' }}>année</strong> concernée en haut de la page.</li>
|
||
<li>Onglet <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2561</code> si vous avez des plateformes françaises soumises au PFU.</li>
|
||
<li>Onglets <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2778-SD</code> puis <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2047</code> si vous avez des plateformes étrangères — le suivi mensuel du 2778-SD documente le détail, la vue « Données 2047 » regroupe l'annuel par pays.</li>
|
||
<li>Onglet <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2042-C PRO</code> si vous avez des plateformes de type PSAN (crowdlending sur actifs numériques) — indépendant des onglets précédents, la case 5HQ se reporte séparément sur l'imprimé 2042-C PRO.</li>
|
||
<li>Onglet <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>2042</code> en dernier : sa vue « Données 2042 » et sa synthèse fiscale récapitulent toutes les cases (2TT, 2TR, 2BH, 2CK, 2TY) à saisir sur le site des impôts.</li>
|
||
</ol>
|
||
|
||
<p>
|
||
Les montants affichés dans les vues « Données » et les cases officielles sont arrondis à l'euro, comme
|
||
l'exigent les formulaires CERFA (les montants intermédiaires du suivi mensuel restent au centime près,
|
||
pour la traçabilité).
|
||
</p>
|
||
|
||
<p style={{ marginBottom: 0 }}>
|
||
Comme rappelé sur la page elle-même : ce module est une <strong style={{ color: 'var(--text)' }}>aide à la
|
||
préparation</strong> de votre déclaration, il ne s'y substitue pas. Contrôlez chaque case avant de la
|
||
reporter — vous restez seul responsable de l'exactitude de votre déclaration.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
<FaqSectionTitle>API et Serveur MCP pour l'IA</FaqSectionTitle>
|
||
|
||
<FaqItem question="Comment configurer le serveur MCP pour l'utiliser dans Claude Desktop" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Le serveur MCP tourne déjà en continu (service Docker <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending-mcp</code>,
|
||
exposé via Traefik) — vous n'avez rien à installer ni à laisser tourner sur votre machine. Il
|
||
suffit de connecter Claude Desktop à l'URL publique.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Étapes</h4>
|
||
<ol style={{ margin: '0 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li>Générez une clé API : <strong style={{ color: 'var(--text)' }}>Mon compte → Clés API → Nouvelle clé</strong> (par exemple nommée « Claude Desktop »).</li>
|
||
<li>Allez dans <strong style={{ color: 'var(--text)' }}>Mon compte → Serveur MCP</strong> et renseignez l'URL publique
|
||
(<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>{mcpConfigUrl}</code>{appInfo.mcpUrl ? ' — déjà pré-rempli si vous ne l\'avez pas modifié' : ''}) ainsi que la clé générée.</li>
|
||
<li>Copiez la configuration générée dans <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>claude_desktop_config.json</code> (Réglages
|
||
→ Développeur → Serveurs MCP locaux → Modifier la config) — le mécanisme passe par
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}> mcp-remote</code> (avec le wrapper <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>cmd /c</code> sous
|
||
Windows), généré automatiquement pour vous.</li>
|
||
<li>Redémarrez complètement Claude Desktop.</li>
|
||
</ol>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Sécurité</h4>
|
||
<ul style={{ margin: '0 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li>Le point d'entrée public n'a <strong style={{ color: 'var(--text)' }}>volontairement aucune restriction d'IP</strong> (accessible
|
||
depuis n'importe où, pour un usage nomade) : la clé API est donc la seule barrière d'accès. Traitez-la comme un
|
||
mot de passe, et révoquez-la immédiatement en cas de doute (Mon compte → Clés API).</li>
|
||
<li>Limite de 60 requêtes/minute par IP (au-delà, erreur 429) et fermeture automatique des sessions inactives
|
||
depuis plus de 30 minutes — aucune donnée de session n'est conservée entre deux connexions.</li>
|
||
<li>L'outil <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_fetch_url</code> (lecture d'une page web arbitraire) reste
|
||
<strong style={{ color: 'var(--text)' }}> désactivé</strong> sur ce serveur.</li>
|
||
</ul>
|
||
<p style={{ marginBottom: 0 }}>
|
||
Si la connexion reste bloquée sans erreur visible, la cause est presque toujours la même :
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}> npx</code> qui échoue silencieusement à joindre le registre npm — voir la
|
||
section Dépannage de <strong style={{ color: 'var(--text)' }}>Mon compte → Serveur MCP</strong>.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
<FaqItem question="Comment utiliser le serveur MCP au quotidien ? (fonctions disponibles et exemples)" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Une fois connecté, Claude (Desktop ou tout autre client MCP) peut consulter votre portefeuille en langage
|
||
naturel — il choisit lui-même le bon outil selon votre question. Le serveur est <strong style={{ color: 'var(--text)' }}>strictement
|
||
en lecture seule</strong> : aucune donnée n'est jamais créée, modifiée ou supprimée depuis une conversation. Toute
|
||
saisie (nouvel investissement, remboursement…) reste manuelle dans l'application.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Fonctions disponibles</h4>
|
||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 'var(--fs-sm)', margin: '0 0 14px' }}>
|
||
<tbody>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_get_investisseur</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Profil de l'investisseur lié à la clé API (nom, type famille/entreprise, régime fiscal). Avec une clé « Famille et entreprises », renvoie la liste des profils du foyer.</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_get_dashboard</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>KPIs du portefeuille : capital investi, capital en risque, montant remboursé, intérêts bruts/nets, dépôts/retraits, gain net depuis le début (frais hors remboursement déduits) — filtrable par année.</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_list_investissements</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Liste des investissements (projet, émetteur, plateforme, montant, taux, durée, statut), filtrable par statut.</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_get_investissement</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Détail complet d'un investissement (par id), y compris ses remboursements réels perçus et les frais qui lui sont liés (souscription, gestion, distribution).</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_list_remboursements</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Historique des remboursements perçus (toutes plateformes), avec le frais éventuellement retenu sur chacun, filtrable par période.</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_list_frais_operations</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Frais liés aux investissements — souscription, gestion, distribution — toutes plateformes, filtrable par période.</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_list_depots_retraits</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Historique des mouvements de cash (dépôts et retraits), du plus récent au plus ancien.</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_list_objectifs</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Objectifs de versement et de capital investi (Paramétrage → Fixation des objectifs), à comparer au réalisé. Filtrable par type et par année.</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_get_taxreport</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>
|
||
Synthèse fiscale annuelle (CERFA 2042/2561/2047/2778-SD) — aide à la préparation de la déclaration,
|
||
calculée avec les mêmes règles que la page Fiscalité. Ce n'est pas une source officielle : à vérifier
|
||
avant tout report sur votre déclaration.
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_fetch_url</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>
|
||
<em>Développement local uniquement</em>, désactivé par défaut. Lit une page web (ex. annonce de projet sur
|
||
une plateforme) et en extrait le texte propre — c'est à vous d'en reprendre les informations utiles pour
|
||
créer l'investissement manuellement, l'outil ne saisit rien lui-même.
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Exemples de questions</h4>
|
||
<ul style={{ margin: '0 0 12px 16px', paddingLeft: 0, lineHeight: 2 }}>
|
||
<li>« Quel est mon encours de crowdlending actuellement ? »</li>
|
||
<li>« Quel a été mon rendement (intérêts nets) en 2026 ? »</li>
|
||
<li>« Liste-moi les investissements en retard ou en procédure. »</li>
|
||
<li>« Donne-moi le détail de l'investissement 42, avec ses remboursements. »</li>
|
||
<li>« Quels remboursements ai-je reçus entre le 1er et le 30 juin 2026 ? »</li>
|
||
<li>« Quels ont été mes derniers dépôts et retraits ? »</li>
|
||
<li>« Combien ai-je payé de frais cette année, et sur quels investissements ? »</li>
|
||
<li>« Regarde cette annonce de projet et propose-moi les infos pour créer l'investissement : [URL] »
|
||
(développement local, avec <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>crowdlending_fetch_url</code> activé)</li>
|
||
<li>« Ai-je atteint mon objectif de versement pour {new Date().getFullYear()} ? »</li>
|
||
<li>« Prépare-moi une synthèse fiscale pour l'année {new Date().getFullYear() - 1}. »</li>
|
||
</ul>
|
||
<p style={{ marginBottom: 0 }}>
|
||
Ces exemples fonctionnent aussi bien en dev qu'en prod dès lors que le serveur correspondant est connecté
|
||
(voir les FAQ de configuration ci-dessus) — les neuf premiers outils sont identiques dans les deux environnements.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
<FaqItem question="Comment interroger mon portefeuille depuis Excel avec Power Query ?" openQuestion={openQuestion} setOpenQuestion={setOpenQuestion}>
|
||
<p style={{ marginTop: 0 }}>
|
||
Comme le serveur MCP, Power Query s'appuie sur l'API v1 (lecture seule) via une clé API.
|
||
Power Query est intégré nativement à Excel (365 / 2016 et plus, Windows ou Mac) — rien à
|
||
installer. Chaque étape ci-dessous correspond à un écran que vous pouvez capturer pour
|
||
illustrer votre propre guide.
|
||
</p>
|
||
|
||
<div>
|
||
<DownloadLink href="/powerquery/crowdlending-powerquery-exemple.xlsb">
|
||
Télécharger le classeur complet (.xlsb)
|
||
</DownloadLink>
|
||
</div>
|
||
<p style={{ marginTop: 0, marginBottom: 16 }}>
|
||
Le classeur ci-dessus contient déjà les 7 requêtes ci-dessous, prêtes à charger — il ne
|
||
reste qu'à renseigner votre clé (étape 1). Vous pouvez aussi tout reconstruire à la main
|
||
avec les fichiers <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>.pq</code> individuels
|
||
proposés à chaque étape ci-dessous.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Étape 1 — Générer une clé API</h4>
|
||
<ol style={{ margin: '0 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li><strong style={{ color: 'var(--text)' }}>Mon compte → Clés API → Nouvelle clé</strong>.</li>
|
||
<li>Donnez-lui un nom explicite (ex. « Excel »), validez, puis copiez immédiatement la clé
|
||
affichée — elle ne sera plus visible en clair ensuite.</li>
|
||
</ol>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Étape 2 — Créer les deux requêtes de connexion</h4>
|
||
<p>
|
||
Dans Excel : <strong style={{ color: 'var(--text)' }}>Données → Obtenir des données → À partir d'autres
|
||
sources → Requête vide</strong>. Une nouvelle requête « Requête1 » apparaît dans l'éditeur Power Query.
|
||
</p>
|
||
<ol style={{ margin: '0 0 8px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li>Renommez-la <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>ApiBaseUrl</code> (double-clic
|
||
sur son nom dans le volet Requêtes), puis <strong style={{ color: 'var(--text)' }}>Affichage → Éditeur avancé</strong>,
|
||
effacez le contenu par défaut et collez :</li>
|
||
</ol>
|
||
<pre style={{ margin: '0 0 12px', padding: '12px 16px', background: 'var(--surface-2)', borderRadius: 8, fontFamily: 'monospace', fontSize: 'var(--fs-sm)', color: 'var(--text)', whiteSpace: 'pre-wrap', overflowX: 'auto' }}>
|
||
{`"http://localhost:4000/api/v1"`}
|
||
</pre>
|
||
<DownloadLink href="/powerquery/queries/ApiBaseUrl.pq">Télécharger ApiBaseUrl.pq</DownloadLink>
|
||
<img
|
||
src="/powerquery/apibaseurl-editeur-avance.png"
|
||
alt="Éditeur avancé Power Query — requête ApiBaseUrl avec l'URL de l'API en production"
|
||
style={{ width: '100%', maxWidth: 600, borderRadius: 8, border: '1px solid var(--border)', display: 'block', margin: '0 0 16px' }}
|
||
onError={(e) => { e.currentTarget.style.display = 'none'; }}
|
||
/>
|
||
<ol start={2} style={{ margin: '0 0 8px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li>Cliquez <strong style={{ color: 'var(--text)' }}>Terminé</strong>, puis <strong style={{ color: 'var(--text)' }}>Accueil → Fermer et charger dans… → Uniquement créer la connexion</strong> (pas besoin d'un tableau pour celle-ci).</li>
|
||
<li>Répétez l'opération pour une seconde requête vide nommée <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>ApiKey</code> :</li>
|
||
</ol>
|
||
<pre style={{ margin: '0 0 12px', padding: '12px 16px', background: 'var(--surface-2)', borderRadius: 8, fontFamily: 'monospace', fontSize: 'var(--fs-sm)', color: 'var(--text)', whiteSpace: 'pre-wrap', overflowX: 'auto' }}>
|
||
{`"clk_live_VOTRE_CLE_API"`}
|
||
</pre>
|
||
<DownloadLink href="/powerquery/queries/ApiKey.pq">Télécharger ApiKey.pq</DownloadLink>
|
||
<img
|
||
src="/powerquery/apikey-editeur-avance.png"
|
||
alt="Éditeur avancé Power Query — requête ApiKey avec la clé API renseignée"
|
||
style={{ width: '100%', maxWidth: 600, borderRadius: 8, border: '1px solid var(--border)', display: 'block', margin: '0 0 16px' }}
|
||
onError={(e) => { e.currentTarget.style.display = 'none'; }}
|
||
/>
|
||
<p>Remplacez par la clé copiée à l'étape 1, entre guillemets. Même chose : Terminé → Uniquement créer la connexion.</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Étape 3 — La fonction technique fnApiGet</h4>
|
||
<p>
|
||
Une troisième requête vide, nommée <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>fnApiGet</code>,
|
||
fait l'appel HTTP et transmet la clé dans l'en-tête <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>X-API-Key</code> —
|
||
les requêtes suivantes la réutiliseront par son nom, sans la récrire :
|
||
</p>
|
||
<pre style={{ margin: '0 0 12px', padding: '12px 16px', background: 'var(--surface-2)', borderRadius: 8, fontFamily: 'monospace', fontSize: 'var(--fs-sm)', color: 'var(--text)', whiteSpace: 'pre-wrap', overflowX: 'auto' }}>
|
||
{`(chemin as text, optional parametres as nullable record) as any =>
|
||
let
|
||
parametresBruts = if parametres = null then [] else parametres,
|
||
champsUtiles = List.Select(
|
||
Record.FieldNames(parametresBruts),
|
||
each Record.Field(parametresBruts, _) <> null and Record.Field(parametresBruts, _) <> ""
|
||
),
|
||
parametresNettoyes = Record.SelectFields(parametresBruts, champsUtiles),
|
||
reponse = Web.Contents(
|
||
ApiBaseUrl,
|
||
[
|
||
RelativePath = chemin,
|
||
Headers = [#"X-API-Key" = ApiKey, #"Accept" = "application/json"],
|
||
Query = parametresNettoyes
|
||
]
|
||
),
|
||
resultat = Json.Document(reponse)
|
||
in
|
||
resultat`}
|
||
</pre>
|
||
<DownloadLink href="/powerquery/queries/fnApiGet.pq">Télécharger fnApiGet.pq</DownloadLink>
|
||
<img
|
||
src="/powerquery/fnapiget-editeur-avance.png"
|
||
alt="Éditeur avancé Power Query — fonction fnApiGet"
|
||
style={{ width: '100%', maxWidth: 700, borderRadius: 8, border: '1px solid var(--border)', display: 'block', margin: '0 0 16px' }}
|
||
onError={(e) => { e.currentTarget.style.display = 'none'; }}
|
||
/>
|
||
<p>Terminé → Fermer et charger dans… → Uniquement créer la connexion (ce n'est pas une donnée à afficher).</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Étape 4 — Première requête de données : Investissements</h4>
|
||
<p>Une nouvelle requête vide, nommée <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>Investissements</code> :</p>
|
||
<pre style={{ margin: '0 0 12px', padding: '12px 16px', background: 'var(--surface-2)', borderRadius: 8, fontFamily: 'monospace', fontSize: 'var(--fs-sm)', color: 'var(--text)', whiteSpace: 'pre-wrap', overflowX: 'auto' }}>
|
||
{`let
|
||
// Pour filtrer par statut, remplacez null par [statut = "rembourse"]
|
||
// Statuts possibles : en_cours, rembourse, en_retard, procedure, cloture
|
||
Source = fnApiGet("/investissements", null),
|
||
Resultat = Table.FromRecords(Source)
|
||
in
|
||
Resultat`}
|
||
</pre>
|
||
<DownloadLink href="/powerquery/queries/Investissements.pq">Télécharger Investissements.pq</DownloadLink>
|
||
<img
|
||
src="/powerquery/investissements-editeur-avance.png"
|
||
alt="Éditeur avancé Power Query — requête Investissements avec aperçu des données chargées"
|
||
style={{ width: '100%', maxWidth: 700, borderRadius: 8, border: '1px solid var(--border)', display: 'block', margin: '0 0 16px' }}
|
||
onError={(e) => { e.currentTarget.style.display = 'none'; }}
|
||
/>
|
||
<p>
|
||
Cette fois-ci, <strong style={{ color: 'var(--text)' }}>Terminé → Fermer et charger</strong> (le bouton
|
||
simple, pas « … ») : la requête s'ajoute comme tableau dans une nouvelle feuille, avec vos
|
||
investissements en ligne et en colonnes.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Étape 5 — Actualiser</h4>
|
||
<p style={{ marginBottom: 0 }}>
|
||
<strong style={{ color: 'var(--text)' }}>Données → Actualiser tout</strong> (ou Ctrl+Alt+F5) à tout moment
|
||
pour recharger les données depuis l'API — utile après un nouvel investissement ou remboursement
|
||
saisi dans l'app.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Aller plus loin — les autres requêtes</h4>
|
||
<p>Même principe (requête vide → nom exact → éditeur avancé → coller → charger) pour :</p>
|
||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 'var(--fs-sm)', margin: '0 0 14px' }}>
|
||
<tbody>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>Investisseur</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Profil investisseur (ou liste des membres si clé « Famille et entreprises »).</td>
|
||
<td style={{ padding: '8px 0 8px 10px', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<DownloadLink href="/powerquery/queries/Investisseur.pq">.pq</DownloadLink>
|
||
</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>Dashboard</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>KPIs du portefeuille, au format « Indicateur / Valeur » (facile à croiser dans un TCD).</td>
|
||
<td style={{ padding: '8px 0 8px 10px', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<DownloadLink href="/powerquery/queries/Dashboard.pq">.pq</DownloadLink>
|
||
</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>Remboursements</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Historique des remboursements, filtrable par période.</td>
|
||
<td style={{ padding: '8px 0 8px 10px', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<DownloadLink href="/powerquery/queries/Remboursements.pq">.pq</DownloadLink>
|
||
</td>
|
||
</tr>
|
||
<tr style={{ borderBottom: '1px solid var(--border)' }}>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>DépôtsRetraits</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>Historique des mouvements de cash.</td>
|
||
<td style={{ padding: '8px 0 8px 10px', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<DownloadLink href="/powerquery/queries/DepotsRetraits.pq">.pq</DownloadLink>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td style={{ padding: '8px 10px 8px 0', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>fnDetailInvestissement</code>
|
||
</td>
|
||
<td style={{ padding: '8px 0', verticalAlign: 'top' }}>
|
||
Fonction avancée : sur la table <em>Investissements</em>, colonne personnalisée{' '}
|
||
<code style={{ fontFamily: 'monospace' }}>= fnDetailInvestissement([id])</code>{' '}
|
||
pour ramener le détail + les remboursements de chaque prêt.
|
||
</td>
|
||
<td style={{ padding: '8px 0 8px 10px', verticalAlign: 'top', whiteSpace: 'nowrap' }}>
|
||
<DownloadLink href="/powerquery/queries/fnDetailInvestissement.pq">.pq</DownloadLink>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>
|
||
Toutes ces requêtes sont déjà incluses dans le classeur téléchargeable en haut de cette fiche —
|
||
les fichiers <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>.pq</code> ci-dessus
|
||
ne sont utiles que si vous préférez les coller vous-même dans un classeur existant.
|
||
</p>
|
||
|
||
<h4 style={{ margin: '16px 0 8px', color: 'var(--text)' }}>Dépannage</h4>
|
||
<ul style={{ margin: '0 0 12px 16px', paddingLeft: 0, lineHeight: 1.8 }}>
|
||
<li><strong style={{ color: 'var(--text)' }}>« Impossible de se connecter au service distant »</strong> — le
|
||
backend n'est pas démarré, ou <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>ApiBaseUrl</code> est
|
||
incorrecte (vérifiez le port et le suffixe <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>/api/v1</code>).</li>
|
||
<li><strong style={{ color: 'var(--text)' }}>Erreur 401 / clé invalide</strong> — régénérez une clé dans
|
||
Mon compte → Clés API et mettez à jour la requête <code style={{ background: 'var(--surface-2)', padding: '1px 5px', borderRadius: 4 }}>ApiKey</code>.</li>
|
||
<li><strong style={{ color: 'var(--text)' }}>Avertissement de confidentialité au premier chargement</strong> —
|
||
normal pour toute nouvelle source Web dans Power Query ; choisissez « Organisationnel » ou « Public »
|
||
selon votre contexte.</li>
|
||
</ul>
|
||
<p style={{ marginBottom: 0 }}>
|
||
Comme le serveur MCP, ces requêtes sont strictement en lecture seule : aucune saisie n'est possible
|
||
depuis Excel, toute modification reste à faire dans l'application.
|
||
</p>
|
||
</FaqItem>
|
||
|
||
</div>
|
||
)}
|
||
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|