Changes to be committed:
Deploy via Portainer / deploy (push) Successful in 0s

new file:   .gitea/workflows/deploy.yml
	modified:   compta/templates/compta/base.html
	modified:   compta/templates/compta/gestion.html
	modified:   compta/templates/compta/import_csv.html
	modified:   compta/templates/compta/saisie_paiement.html
	modified:   compta/views_gestion.py
	modified:   compta/views_import.py
	modified:   compta/views_saisie.py
This commit is contained in:
2026-07-12 00:20:33 +02:00
parent 757c0850c3
commit 888bcfa213
8 changed files with 370 additions and 289 deletions
+51 -58
View File
@@ -1,49 +1,38 @@
{% load l10n %}<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JB Compta — Import</title>
{% extends "compta/base.html" %}
{% load l10n %}
{% block titre %}Importer{% endblock %}
{% block extrastyle %}
<style>
:root { --bg:#0f172a; --card:#1e293b; --txt:#e2e8f0; --muted:#94a3b8;
--accent:#38bdf8; --ok:#34d399; --bad:#f87171; }
* { box-sizing:border-box; }
body { margin:0; font-family:system-ui,Segoe UI,Roboto,sans-serif;
background:var(--bg); color:var(--txt); padding:24px; }
h1 { margin:0 0 4px; font-size:22px; } h2{font-size:15px;color:var(--muted);margin:0 0 8px;}
a { color:var(--accent); }
.sub { color:var(--muted); margin-bottom:14px; }
.card { background:var(--card); border:1px solid #334155; border-radius:12px; padding:16px; margin-bottom:16px; }
.card.indy { border-color:#0e7490; }
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:90px; font-family:ui-monospace,monospace; }
.ic label { display:block; font-size:12px; color:var(--muted); margin:10px 0 4px; }
.ic input, .ic select, .ic textarea { width:100%; background:var(--panel); }
.ic textarea { min-height:90px; font-family:ui-monospace,monospace; }
.ic .card { margin-bottom:16px; }
.ic .card.indy { border-color:#0e7490; }
.grid3 { display:grid; grid-template-columns:2fr 1fr 1fr; gap:12px; }
.grid2 { display:grid; grid-template-columns:1fr 1fr; gap:12px; }
@media(max-width:700px){ .grid3,.grid2{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: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; }
.ic .actions { display:flex; gap:12px; margin-top:14px; flex-wrap:wrap; }
.ic table { font-size:13px; }
.ic th, .ic td { padding:5px 7px; text-align:left; }
.ic td input, .ic td select { padding:6px 8px; }
.ic .num { text-align:right; }
code { background:var(--panel); padding:1px 6px; border-radius:5px; }
</style>
</head>
<body>
<h1>Importer un relevé</h1>
<div class="sub"><a href="/dashboard/">← Tableau de bord</a> · <a href="/saisie/">Saisie manuelle</a></div>
{% endblock %}
{% block topbar %}
<h1>Importer un relevé</h1>
<div class="sub">Synchronisation Indy, CSV, ou capture d'écran (OCR) — avec aperçu éditable et anti-doublon.</div>
{% endblock %}
{% block content %}
<div class="ic">
{% if erreurs %}{% for e in erreurs %}<div class="msg bad">{{ e }}</div>{% endfor %}{% endif %}
{% if resultat %}
<div class="msg ok">Import terminé :
<div class="msg">Import terminé :
{% for k, v in resultat.items %}{{ v }} {{ k }}{% if not forloop.last %} · {% endif %}{% endfor %}.
Voir <a href="/admin/compta/depense/">dépenses</a> · <a href="/admin/compta/facture/">factures</a>.</div>
Voir <a href="/gestion/">Entrées / sorties</a>.</div>
{% endif %}
{% if ocr_debug %}
@@ -60,7 +49,7 @@
{% csrf_token %}
<h2>① Synchroniser depuis Indy (recommandé)</h2>
<div class="sub">Récupère tes transactions directement depuis l'API Indy. Anti-doublon automatique.
· <a href="/import/bookmarklet/">📌 Installer le favori « Indy → CSV »</a> (le plus simple, depuis ton navigateur)</div>
· <a href="/import/bookmarklet/">Installer le favori « Indy → CSV »</a> (le plus simple, depuis ton navigateur)</div>
<div class="grid3">
<div>
<label>Entreprise</label>
@@ -74,7 +63,7 @@
<label>Token Indy (Bearer, sans « Bearer ») — mémorisé sur l'entreprise, expire ~1 h</label>
<textarea name="indy_token" placeholder="eyJ..."></textarea>
<div class="actions">
<button type="submit" name="action" value="indy" class="primary">Récupérer depuis Indy</button>
<button type="submit" name="action" value="indy" class="btn-primary">Récupérer depuis Indy</button>
</div>
</form>
@@ -98,10 +87,10 @@
</div>
<label>…ou fichier CSV</label>
<input type="file" name="fichier" accept=".csv,.txt">
<label>…ou colle des lignes CSV <span class="sub">(date ; libelle ; categorie ; activite ; taux_tva ; regime ; montant)</span></label>
<label>…ou colle des lignes CSV <span class="muted">(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" class="primary">Analyser / Aperçu</button>
<button type="submit" name="action" value="preview" class="btn-primary">Analyser / Aperçu</button>
</div>
</form>
{% endif %}
@@ -111,6 +100,7 @@
{% csrf_token %}
<input type="hidden" name="entreprise" value="{{ entreprise_id }}">
<h2>Aperçu éditable — {{ lignes|length }} ligne(s){% if source == 'indy' %} (Indy){% elif source == 'ocr' %} (OCR){% endif %}</h2>
<div class="table-wrap">
<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>
@@ -138,27 +128,30 @@
{% endfor %}
</tbody>
</table>
</div>
<div class="actions">
<button type="submit" name="action" value="save" class="primary">Enregistrer ces opérations</button>
<button type="submit" name="action" value="save" class="btn-primary">Enregistrer ces opérations</button>
<a href="/import/"><button type="button">Recommencer</button></a>
</div>
</form>
{% endif %}
</div>
{% endblock %}
<script>
window.addEventListener('paste', function(e){
var input = document.getElementById('imgInput');
if(!input || !e.clipboardData) return;
for(var i=0; i<e.clipboardData.items.length; i++){
var it = e.clipboardData.items[i];
if(it.type && it.type.indexOf('image') === 0){
var dt = new DataTransfer(); dt.items.add(it.getAsFile()); input.files = dt.files;
var info = document.getElementById('pasteInfo');
if(info){ info.textContent = 'Image collée — clique « Analyser ».'; info.style.color = '#34d399'; }
e.preventDefault(); break;
}
{% block scripts %}
<script>
window.addEventListener('paste', function(e){
var input = document.getElementById('imgInput');
if(!input || !e.clipboardData) return;
for(var i=0; i<e.clipboardData.items.length; i++){
var it = e.clipboardData.items[i];
if(it.type && it.type.indexOf('image') === 0){
var dt = new DataTransfer(); dt.items.add(it.getAsFile()); input.files = dt.files;
var info = document.getElementById('pasteInfo');
if(info){ info.textContent = 'Image collée — clique « Analyser ».'; info.style.color = '#34d399'; }
e.preventDefault(); break;
}
});
</script>
</body>
</html>
}
});
</script>
{% endblock %}