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:
@@ -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 %}
|
||||
|
||||
Reference in New Issue
Block a user