OCR pytesseract dans l'import + apercu editable

This commit is contained in:
2026-06-30 08:52:45 +02:00
parent ab8af8d4bb
commit 60aab53227
4 changed files with 287 additions and 133 deletions
+65 -46
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JB Compta — Import CSV</title>
<title>JB Compta — Import</title>
<style>
:root { --bg:#0f172a; --card:#1e293b; --txt:#e2e8f0; --muted:#94a3b8;
--accent:#38bdf8; --ok:#34d399; --bad:#f87171; }
@@ -12,84 +12,103 @@
background:var(--bg); color:var(--txt); padding:24px; }
h1 { margin:0 0 4px; font-size:22px; } h2{font-size:15px;color:var(--muted);}
a { color:var(--accent); }
.sub { color:var(--muted); margin-bottom:16px; }
.sub { color:var(--muted); margin-bottom:14px; }
.card { background:var(--card); border:1px solid #334155; border-radius:12px; padding:16px; margin-bottom:16px; }
label { display:block; font-size:12px; color:var(--muted); margin:8px 0 4px; }
input, select, textarea { background:#0f172a; color:var(--txt); border:1px solid #334155;
border-radius:8px; padding:8px 10px; font-size:14px; width:100%; }
textarea { min-height:140px; font-family:ui-monospace,monospace; }
textarea { min-height:110px; font-family:ui-monospace,monospace; }
.grid3 { display:grid; grid-template-columns:2fr 1fr 1fr; gap:12px; }
@media(max-width:700px){ .grid3{grid-template-columns:1fr;} }
button { cursor:pointer; border-radius:8px; border:1px solid #334155; background:var(--card);
color:var(--txt); padding:9px 16px; font-size:14px; }
button.primary { background:var(--accent); color:#04263a; border:none; font-weight:600; }
.actions { display:flex; gap:12px; margin-top:12px; }
table { width:100%; border-collapse:collapse; font-size:13px; }
th,td { padding:6px 8px; border-bottom:1px solid #334155; text-align:right; }
th:first-child,td:first-child,th:nth-child(2),td:nth-child(2),th:nth-child(3),td:nth-child(3) { text-align:left; }
th,td { padding:4px 6px; border-bottom:1px solid #334155; text-align:left; }
td input, td select { padding:5px 7px; }
.num { text-align:right; }
code { background:#0f172a; padding:1px 6px; border-radius:5px; }
.msg { padding:10px 14px; border-radius:8px; margin-bottom:8px; }
.msg.bad { background:#7f1d1d; } .msg.ok { background:#064e3b; }
.pill { padding:1px 8px; border-radius:99px; font-size:12px; background:#334155; }
</style>
</head>
<body>
<h1>Import d'un relevé (CSV)</h1>
<h1>Importer un relevé</h1>
<div class="sub"><a href="/dashboard/">← Tableau de bord</a> · <a href="/saisie/">Saisie manuelle</a></div>
<div class="card">
<h2>Format attendu</h2>
<div class="sub">Colonnes séparées par <code>;</code> (en-tête facultatif) :</div>
<code>date ; libelle ; categorie ; activite ; taux_tva ; regime ; montant</code>
<div class="sub" style="margin-top:8px">
<b>montant</b> négatif = dépense, positif = vente · <b>regime</b> : nationale / intracom / import (vide = nationale)
· <b>activite</b> : vente / service_bic / service_bnc · une catégorie « neutre » (TVA payée, Urssaf, remboursement) n'entre pas dans les calculs.<br>
Exemple : <code>2026-06-25;ALTISSIMO;Vente de produits finis;vente;20;;168.40</code>
</div>
</div>
{% if erreurs %}{% for e in erreurs %}<div class="msg bad">{{ e }}</div>{% endfor %}{% endif %}
{% if resultat %}
<div class="msg ok">Import terminé :
{% for k, v in resultat.items %}{{ v }} {{ k }}{% if not forloop.last %} · {% endif %}{% endfor %}.
Va voir dans <a href="/admin/compta/depense/">les dépenses</a> et
<a href="/admin/compta/facture/">les factures</a>.
</div>
Voir <a href="/admin/compta/depense/">dépenses</a> · <a href="/admin/compta/facture/">factures</a>.</div>
{% endif %}
{% if not lignes %}
<form method="post" enctype="multipart/form-data" class="card">
{% csrf_token %}
<label>Entreprise</label>
<select name="entreprise" required>
{% for e in entreprises %}<option value="{{ e.pk }}" {% if e.pk == entreprise_id %}selected{% endif %}>{{ e.nom }}</option>{% endfor %}
</select>
<label>Fichier CSV</label>
<div class="grid3">
<div>
<label>Entreprise</label>
<select name="entreprise" required>
{% for e in entreprises %}<option value="{{ e.pk }}" {% if e.pk == entreprise_id %}selected{% endif %}>{{ e.nom }}</option>{% endfor %}
</select>
</div>
<div>
<label>Année (pour l'OCR)</label>
<input type="number" name="annee" value="{{ annee_defaut }}">
</div>
<div>
<label>Capture d'écran (OCR)</label>
<input type="file" name="image" accept="image/*">
</div>
</div>
<label>…ou fichier CSV</label>
<input type="file" name="fichier" accept=".csv,.txt">
<label>…ou colle directement les lignes ici</label>
<label>…ou colle des lignes CSV <span class="sub">(date ; libelle ; categorie ; activite ; taux_tva ; regime ; montant)</span></label>
<textarea name="texte" placeholder="2026-06-25;ALTISSIMO;Vente de produits finis;vente;20;;168.40">{{ texte }}</textarea>
<div class="actions">
<button type="submit" name="action" value="preview">Aperçu</button>
<button type="submit" name="action" value="import" class="primary">Importer</button>
<button type="submit" name="action" value="preview" class="primary">Analyser / Aperçu</button>
</div>
<div class="sub" style="margin-top:8px">L'OCR pré-remplit les lignes ; tu corriges la catégorie et le taux dans l'aperçu avant d'enregistrer.</div>
</form>
{% endif %}
{% if lignes %}
<div class="card">
<h2>Aperçu — {{ lignes|length }} ligne(s)</h2>
<table>
<thead><tr><th>#</th><th>Date</th><th>Libellé</th><th>Catégorie</th><th>Type</th><th>Taux</th><th>Régime</th><th>Montant</th></tr></thead>
<tbody>
{% for l in lignes %}
<tr>
<td>{{ l.n }}</td><td>{{ l.date }}</td><td>{{ l.libelle }}</td>
<td>{{ l.categorie_nom }}{% if l.categorie_nom and not l.categorie %} ⚠️{% endif %}</td>
<td><span class="pill">{{ l.type }}</span></td>
<td>{{ l.taux }} %</td><td>{{ l.regime }}</td><td>{{ l.montant }} €</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="sub" style="margin-top:8px">⚠️ = catégorie non reconnue (sera laissée vide). Vérifie, puis clique « Importer ».</div>
<form method="post" class="card">
{% csrf_token %}
<input type="hidden" name="entreprise" value="{{ entreprise_id }}">
<h2>Aperçu éditable — {{ lignes|length }} ligne(s) {% if source == 'ocr' %}(OCR){% endif %}</h2>
<table>
<thead><tr><th>Date</th><th>Libellé</th><th>Catégorie</th><th>Régime TVA</th><th>Taux %</th><th>Montant €</th><th>Type</th></tr></thead>
<tbody>
{% for l in lignes %}
<tr>
<td><input type="date" name="l_date" value="{{ l.date }}" style="width:140px"></td>
<td><input type="text" name="l_libelle" value="{{ l.libelle }}"></td>
<td>
<select name="l_categorie">
<option value=""></option>
{% for c in categories %}<option value="{{ c.pk }}" {% if c.pk == l.categorie_id %}selected{% endif %}>{{ c.nom }}</option>{% endfor %}
</select>
</td>
<td>
<select name="l_regime">
{% for val,lab in regimes %}<option value="{{ val }}" {% if val == l.regime %}selected{% endif %}>{{ lab }}</option>{% endfor %}
</select>
</td>
<td><input type="number" step="0.01" name="l_taux" value="{{ l.taux }}" class="num" style="width:70px"></td>
<td><input type="number" step="0.01" name="l_montant" value="{{ l.montant }}" class="num" style="width:100px"></td>
<td>{{ l.type }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="actions">
<button type="submit" name="action" value="save" class="primary">Enregistrer ces opérations</button>
<a href="/import/"><button type="button">Recommencer</button></a>
</div>
</form>
{% endif %}
</body>
</html>