57 lines
5.6 KiB
HTML
57 lines
5.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Indy → CSV — Favori</title>
|
|
<style>
|
|
body{font-family:system-ui,Segoe UI,Roboto,sans-serif;background:#0f172a;color:#e2e8f0;
|
|
max-width:760px;margin:0 auto;padding:28px;line-height:1.5;}
|
|
h1{font-size:22px} h2{font-size:16px;color:#94a3b8;margin-top:26px}
|
|
a.bm{display:inline-block;background:#38bdf8;color:#04263a;font-weight:700;
|
|
padding:10px 18px;border-radius:10px;text-decoration:none;font-size:16px}
|
|
ol{padding-left:20px} li{margin:6px 0}
|
|
textarea{width:100%;height:120px;background:#1e293b;color:#e2e8f0;border:1px solid #334155;
|
|
border-radius:8px;padding:10px;font-family:ui-monospace,monospace;font-size:12px}
|
|
code{background:#1e293b;padding:1px 6px;border-radius:5px}
|
|
.note{color:#94a3b8;font-size:14px}
|
|
.warn{background:#7f1d1d;padding:10px 14px;border-radius:8px;margin-top:10px}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Favori « Indy → CSV »</h1>
|
|
<p class="note">Un clic sur la page Indy → tes transactions sont copiées au format CSV,
|
|
prêtes à coller dans JB Compta. Pas de token à chercher, la 2FA est déjà passée,
|
|
et tout se fait dans ton navigateur (donc pas de souci d'accès serveur).</p>
|
|
|
|
<h2>Installation (30 s)</h2>
|
|
<ol>
|
|
<li>Affiche ta <b>barre de favoris</b> (Ctrl+Maj+B dans Chrome).</li>
|
|
<li><b>Glisse-dépose</b> ce bouton dans la barre de favoris :
|
|
<a class="bm" id="lnk" href="#">Indy → CSV</a></li>
|
|
<li>Va sur <code>app.indy.fr</code> (connecté), puis <b>clique le favori</b>.</li>
|
|
<li>Saisis la période → le CSV est copié → colle-le dans <code>/import/</code> de JB Compta.</li>
|
|
</ol>
|
|
|
|
<div class="warn">Si le glisser-déposer ne marche pas : crée un favori manuellement,
|
|
puis colle le code ci-dessous comme <b>URL</b> du favori.</div>
|
|
|
|
<h2>Code (installation manuelle)</h2>
|
|
<textarea id="ta" readonly onclick="this.select()"></textarea>
|
|
|
|
<h2>Notes</h2>
|
|
<ul class="note">
|
|
<li>À utiliser <b>uniquement</b> quand l'onglet actif est <code>app.indy.fr</code>.</li>
|
|
<li>Aucun secret n'est stocké : le favori lit ta session en cours.</li>
|
|
<li>Si une alerte « Erreur Indy » apparaît, reconnecte-toi à Indy et réessaie.</li>
|
|
<li>Le mapping des catégories (compte comptable → catégorie) est le même que dans l'app.</li>
|
|
</ul>
|
|
|
|
<script>
|
|
var BM = "javascript:(async()=>{const CC=[['701','Vente de produits finis'],['707','Vente de produits finis'],['706','Prestation de services'],['605','Matériel et outillage'],['606','Matériel et outillage'],['607','Matériel et outillage'],['6256','Frais de repas hors domicile'],['6253','Frais de repas hors domicile'],['626','Télécom, fournitures, documentation'],['6181','Télécom, fournitures, documentation'],['6183','Télécom, fournitures, documentation'],['6136','Abonnement logiciel'],['6226','Abonnement logiciel'],['646','Cotisation sociale Urssaf'],['44551','TVA payée'],['44558','TVA payée'],['44583','Remboursement de TVA'],['108','Prélèvement personnel']];const CA=[['701','vente'],['707','vente'],['706','service_bic']];const cat=n=>{n=String(n||'');let b=null;for(const[p,c]of CC){if(n.startsWith(p)&&(!b||p.length>b[0].length))b=[p,c];}return b?b[1]:'';};const act=n=>{n=String(n||'');for(const[p,a]of CA){if(n.startsWith(p))return a;}return '';};const norm=tx=>{const c=tx.totalAmountInCents;if(c==null)return null;const mt=(c/100).toFixed(2);const ss=(tx.subdivisions||[]).filter(s=>!String((s.accounting_account||{}).number||'').startsWith('512'));if(!ss.length)return null;let m=ss[0];for(const s of ss)if(Math.abs(s.amount_in_cents||0)>Math.abs(m.amount_in_cents||0))m=s;const num=String((m.accounting_account||{}).number||'');let rg='',t2=0;if(m.tva_intracom&&m.tva_intracom.type==='eu'){rg='intracom';t2=(m.tva_intracom.rate||0)/100;}else{t2=(m.tva_rate||0)/100;}const lib=(tx.description||tx.raw_description||'').replace(/;/g,' ');return[tx.date||'',lib,cat(num),act(num),String(t2),rg,mt].join(';');};const getTok=()=>new Promise(r=>{const o=indexedDB.open('firebaseLocalStorageDb');o.onsuccess=()=>{try{const q=o.result.transaction('firebaseLocalStorage','readonly').objectStore('firebaseLocalStorage').getAll();q.onsuccess=()=>{const v=(q.result||[]).map(x=>x.value).find(v=>v&&v.stsTokenManager&&v.stsTokenManager.accessToken);r(v?v.stsTokenManager.accessToken:null);};q.onerror=()=>r(null);}catch(e){r(null);}};o.onerror=()=>r(null);});const d1=prompt('Date debut (AAAA-MM-JJ)');if(!d1)return;const d2=prompt('Date fin (AAAA-MM-JJ)');if(!d2)return;const tk=await getTok();const H={'Accept':'application/json','x-client-app-type':'web'};if(tk)H['Authorization']='Bearer '+tk;let all=[],pg=1,tot=1e9;try{while(all.length<tot){const u='/api/transactions/transactions-list?'+new URLSearchParams({search:'',dateFrom:d1,dateTo:d2,page:pg});const r=await fetch(u,{headers:H,credentials:'include'});if(!r.ok)throw new Error('HTTP '+r.status);const j=await r.json();tot=j.nbTransactions!=null?j.nbTransactions:(j.transactions||[]).length;const t=j.transactions||[];if(!t.length)break;all=all.concat(t);pg++;if(pg>60)break;}}catch(e){alert('Erreur Indy : '+e.message);return;}const rows=all.map(norm).filter(Boolean);const NL=String.fromCharCode(10);const csv='date;libelle;categorie;activite;taux_tva;regime;montant'+NL+rows.join(NL);try{await navigator.clipboard.writeText(csv);alert(rows.length+' operations -> CSV copie ! Colle-le dans JB Compta (/import/).');}catch(e){window.prompt('Copie ce CSV (Ctrl+C) :',csv);}})();";
|
|
document.getElementById('lnk').href = BM;
|
|
document.getElementById('ta').value = BM;
|
|
</script>
|
|
</body>
|
|
</html>
|