Files
jb-compta/indy-mcp/bookmarklet.html
T

44 lines
6.4 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">Identique à la page servie par l'app (/import/bookmarklet/). Un clic sur Indy →
CSV copié, prêt à coller dans JB Compta. Pas de token, 2FA déjà passée, tout dans le navigateur.</p>
<h2>Installation</h2>
<ol>
<li>Affiche la barre de favoris (Ctrl+Maj+B).</li>
<li><b>Glisse</b> ce bouton dans la barre : &nbsp; <a class="bm" id="lnk" href="#">Indy → CSV</a></li>
<li>Sur <code>app.indy.fr</code> (connecté), clique le favori, choisis la période (JJ/MM/AAAA).</li>
<li>Colle le CSV dans <code>/import/</code>.</li>
</ol>
<div class="warn">Si le glisser-déposer échoue, crée un favori manuel et colle ce code comme URL :</div>
<textarea id="ta" readonly onclick="this.select()"></textarea>
<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 mk=(t,css)=>{const e=document.createElement(t);if(css)e.style.cssText=css;return e;};const askDates=()=>new Promise(res=>{const t=new Date(),y=t.getFullYear(),mo=String(t.getMonth()+1).padStart(2,'0'),ld=String(new Date(y,t.getMonth()+1,0).getDate()).padStart(2,'0');const ov=mk('div','position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:2147483647;display:flex;align-items:center;justify-content:center');const bx=mk('div','background:#fff;color:#111;padding:20px;border-radius:12px;font-family:sans-serif;min-width:280px');const h=mk('div','font-weight:700;margin-bottom:12px');h.textContent='Indy vers CSV : choisis la periode';const l1=mk('div','font-size:12px;color:#555');l1.textContent='Du';const i1=mk('input','width:100%;margin:4px 0 10px;padding:6px');i1.type='date';i1.value=y+'-'+mo+'-01';const l2=mk('div','font-size:12px;color:#555');l2.textContent='Au';const i2=mk('input','width:100%;margin:4px 0 14px;padding:6px');i2.type='date';i2.value=y+'-'+mo+'-'+ld;const row=mk('div','text-align:right');const an=mk('button','margin-right:8px;padding:6px 12px');an.textContent='Annuler';const ok=mk('button','background:#38bdf8;border:none;padding:6px 14px;border-radius:6px;cursor:pointer');ok.textContent='Recuperer';row.appendChild(an);row.appendChild(ok);[h,l1,i1,l2,i2,row].forEach(x=>bx.appendChild(x));ov.appendChild(bx);document.body.appendChild(ov);ok.onclick=()=>{const a=i1.value,b=i2.value;document.body.removeChild(ov);res([a,b]);};an.onclick=()=>{document.body.removeChild(ov);res([null,null]);};});const[d1,d2]=await askDates();if(!d1||!d2)return;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 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>