Le runner Gitea ne peut pas booter un builder docker-container : le
bootstrap tente de puller moby/buildkit:buildx-stable-1, ce qui échoue.
On utilise le BuildKit intégré au démon (DOCKER_BUILDKIT=1 docker build)
puis docker push, en conservant metadata-action pour tags et labels.
Les tags/labels sont lus ligne à ligne (labels avec espaces préservés).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le runner act_runner ne peut pas booter un conteneur builder
(driver docker-container). On réutilise le démon Docker de l'hôte,
suffisant pour un push linux/amd64.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Build de l'image unique depuis backend.Dockerfile et push vers le
registre (secrets REGISTRY_*). Déclenché sur main, tags v* et manuel.
Tags d'image : latest/main sur la branche par défaut, semver
(X.Y.Z / X.Y / X) sur les tags. Pas de tag par SHA (économie d'espace
registre).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le backend FastAPI sert déjà le SPA buildé : on abandonne le duo
nginx + backend au profit d'une seule image multi-stage (build Vue
puis service par le backend). docker-compose passe à un service
unique, avec PLESNA_DATA_DIR déclarant le stockage persistant.
- backend.Dockerfile : stage node build -> copie frontend/dist,
CMD en `uv run --no-sync` (plus de resync des deps dev au démarrage)
- docker-compose.yml : service unique `app`, volume ./data,
PLESNA_DATA_DIR=/app/data
- supprime frontend/Dockerfile, frontend/nginx.conf, frontend/.dockerignore
- .dockerignore : ignore **/node_modules, data, data_bck
- README : section Production mise à jour
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remplace les parseurs texte+regex (fragiles sur l'alignement en colonnes des
PDF Oralia mal construits) par une extraction géométrique : reconstruction des
lignes visuelles par regroupement vertical tolérant des mots, puis affectation
de chaque valeur à sa colonne via les filets du tableau (pdfplumber find_tables).
Corrections apportées :
- locataires : montant/libellé « divers » dans la bonne colonne (plus le total
cumulé du lot), nom de locataire correct (le logo/en-tête hors filets est
ignoré), lignes multi-période et pages recollées.
- opérations : fournisseur séparé de la description (TOTALENERGIES ≠ DIDIER
NETTOYAGE, PPR ≠ BOUVARD), colonne Déductible remplie, Débit/Crédit distingués,
fournisseur des honoraires reporté sur le bloc, fragments de description
recollés (LATAPY, AUDOUIN).
- code lot : gère « S10 - », « S 17 - » (espace) et « S01 SOLDE » (sans tiret).
Branchés dans extractor.py avec repli sur les anciens parseurs si un tableau n'a
pas de filets détectables. Validés par réconciliation comptable : locataires
124/124 lots, opérations 7/7 PDF et 25/25 catégories, au centime.
Ajoute le bouton « Relancer l'extraction » dans l'écran d'édition : re-extrait
depuis le PDF stocké et met en évidence les différences avec la version
précédente (panneau récapitulatif + anneaux « modifié » sur les cartes). Le diff
des opérations s'aligne par contenu (robuste aux changements d'ordre/nombre).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remplace l'<iframe> (lecteur PDF natif du moteur) par un rendu PDF.js
sur <canvas>, une page par canvas empilee et scrollable. Rendu
identique partout (Qt WebEngine, WebView2, navigateur), worker bundle
localement par Vite -> fonctionne hors-ligne.
Utilise le build *legacy* de pdfjs-dist : il embarque les polyfills
requis par les Chromium embarques (Qt WebEngine, WebView2), plus
anciens que Chrome. Le build par defaut appelle
`Map.prototype.getOrInsertComputed` (proposition JS recente) sans
polyfill, ce qui cassait silencieusement le rendu dans la fenetre
bureau. Le catch logue desormais l'erreur au lieu de l'avaler.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Permet de distribuer l'application en executable Windows double-clic,
sans Python/Node/terminal pour l'utilisateur final.
- `desktop.py` : demarre le serveur sur un port libre dans un thread et
ouvre une fenetre native (pywebview). `PLESNA_DEBUG=1` active les
DevTools. Commande `plesna-gerance desktop` (import paresseux).
- `paths.py` : resolution centralisee des chemins selon le contexte
(dev, executable PyInstaller, surcharge par variables d'env). Les
donnees vont dans un dossier utilisateur inscriptible (%APPDATA%),
les ressources dans le bundle. connection.py/storage.py utilisent
`get_data_dir()`, app.py `resource_path()`.
- app.py : type MIME `.mjs` force (modules ES / worker PDF.js sous
Windows).
- Groupes de deps optionnels desktop / desktop-linux / build.
- packaging/ : spec PyInstaller, build_windows.ps1, installeur Inno
Setup. Workflow GitHub build-windows.yml (runner Windows).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remplace l'appel externe `pdftotext -layout` (poppler-utils) par
pdfplumber, une bibliotheque Python pure : plus aucune dependance
systeme, ce qui permettra d'empaqueter l'application en executable
autonome.
- `read_pdf()` retourne un `PdfContent` (texte layout + mots de la
premiere page avec coordonnees) ; `extract_text_from_pdf()` est
conserve comme wrapper de compatibilite.
- Metadonnees : la reference est desormais extraite via les
coordonnees geometriques des mots (fiable sur l'en-tete
multi-colonnes), regex du destinataire durcie (forme pointee
`S.C.I.`).
- Operations : reduction des espaces multiples dans les descriptions.
- Dockerfile : suppression de poppler-utils.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Config ruff dans pyproject.toml : règles E/W/F/I/UP/B, whitelist des appels
d'injection FastAPI (Depends/File/Form/Query) pour B008, B904 ignoré
(traduction volontaire des exceptions en réponses HTTP)
- Auto-fixes : tri des imports, suppression d'imports inutilisés, annotations
PEP 604, f-strings sans placeholder, modes open redondants
- Suppression de variables inutilisées (config.reset_setting, parser locataires)
ruff check . : All checks passed ; 61 tests OK
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- connection: création de l'engine centralisée dans _build_engine (source
unique de config) ; init_db réutilise reset_connection + get_engine au lieu
de dupliquer create_engine
- service: _normalize_amount garantit qu'un montant non numérique issu de
l'extraction (string, dict…) n'entre jamais en base dans une colonne Float ;
appliqué à solde_montant
- tests: couverture de _normalize_amount et du solde sous forme de string
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- sql_executor: remplace le filtre regex fragile par une autorisation SQLite
(set_authorizer) en complément de mode=ro ; rejette les instructions multiples
- uploads: lecture bornée des PDF (helper read_upload_limited, limite 20 Mo,
HTTP 413) branchée sur /extract et /save-with-pdf
- tests: suite pytest (54 tests) couvrant amounts, dates, storage, sql_executor,
uploads et DatabaseService.save_document ; pytest ajouté en dépendance dev
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Empêche le path traversal du catch-all SPA (vérif is_relative_to dist)
- Migre on_event("startup") vers le handler lifespan de FastAPI
- Masque les exceptions internes des erreurs 500 (log au lieu de str(e))
- Remplace datetime.utcnow déprécié par un helper UTC timezone-aware
- Simplifie except (ValueError, Exception) redondant
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add ConfigPage.vue with two sections: Ollama configuration (URL, model,
timeout) with source badges and per-field reset, and tag management with
inline rename and creation. Add /config route and nav link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a key-value settings table (Setting model) with DB > env > default
resolution chain. Replace hardcoded Ollama constants in ollama_service
with dynamic _get_config() lookups. Add /api/config/ endpoints for
settings CRUD and tag management (create, rename).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clicking the pencil icon in revenus/depenses tables now passes query
params to identify the source row. The edit page auto-expands the
matching section, scrolls to the element, and briefly highlights it
with a blue ring that fades after 2 seconds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch save endpoint from JSON to multipart upload so the PDF file is
sent alongside extracted data and tags.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove pdfjs-dist dependency and simplify PdfPreview component to use
a native browser iframe, reducing bundle size and complexity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add backend and frontend Dockerfiles, docker-compose setup with nginx
reverse proxy, .dockerignore files and Makefile for dev/prod workflows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add new /api/revenus endpoints for rental income data
- GET /summary: KPIs, monthly trends, breakdown by property, top unpaid
- GET /details: detailed rental records with filtering
- GET /by-lot: revenue aggregation by unit
- GET /immeubles: properties list with revenue stats
- Add RevenusPage with full dashboard layout
- 6 KPI cards: total revenue, payments, unpaid, collection rate, active tenants, occupied units
- Monthly evolution chart (rent, payments, unpaid)
- Property breakdown donut chart
- Top unpaid tenants list
- Detailed revenue table with pagination and CSV export
- Add filters panel (property, type, dates, unpaid only, history months)
- Display property address instead of code in all components
- Add navigation link in header (Revenus)
- Add dashboard API endpoints for financial summary, recent revenus, monthly trends, and immeuble shortcuts
- Create new dashboard components: FinancialSummary with sparklines, QuickActions, RecentRevenus, MiniTrendChart, ImmeubleShortcuts
- Refactor HomePage with prominent drag & drop zone and data-driven cards
- Financial cards now show last document data with 6-month trend sparklines in background
- Remove redundant import button, keep single upload zone at top
- Add EditableField component for inline editing of any field
- Update DataRow, LocataireCard, OperationCard to support inline editing
- Add CRUD operations for locataires and operations (add/remove)
- Update JsonViewer to propagate changes via v-model
- Add TagAutocomplete component with search/filter functionality
- Replace select dropdown with autocomplete in TaggingStep
- Backend Python (uv + click + FastAPI)
- CLI: plesna-gerance extract <pdf> pour extraire les donnees
- CLI: plesna-gerance serve pour lancer le serveur API
- API REST: POST /api/extract pour upload et extraction de PDF
- Parsers modulaires: metadata, locataires, operations
- Utilise pdftotext (poppler-utils) pour l'extraction de texte
- Frontend Vue.js + Tailwind CSS
- Interface split-screen: PDF a gauche, donnees a droite
- Preview PDF avec zoom et navigation pages (pdf.js)
- Visualisation structuree des donnees extraites
- Sections depliables: metadata, locataires, operations
- Drag & drop pour upload de PDF
- Extraction automatique a la selection du fichier