feat: balayage de re-extraction de toute la base

Nouvelle page /re-extraction, accessible depuis la liste des documents : elle
rejoue l'extraction de chaque PDF stocke, document par document, avec une
progression et une estimation du temps restant (une extraction prend plusieurs
secondes) et un bouton d'arret. Rien n'est ecrit en base pendant le balayage.

Les documents dont l'extraction change sont listes avec le nombre de
differences par section, deja coches ; les inchanges sont replies et les
documents sans PDF ou en erreur isoles. Le detail depliable reutilise
l'affichage de diff de la re-extraction unitaire (extrait dans
ExtractionDiffDetails). Un seul bouton enregistre toute la selection.

Les tags de depenses sont reportes par signature d'operation et non par index :
une operation ajoutee ou retiree par le nouveau parser ne decale plus les
categories. Ce qui n'est pas reapparie recoit une prediction, modifiable dans le
detail avant enregistrement.

L'edition d'un document et l'application du balayage passent par
PUT /api/documents/{id}, qui vise le document par son ID.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 05:17:49 +02:00
parent 6f2530014f
commit 5f3a26e7d7
8 changed files with 784 additions and 72 deletions

View File

@@ -262,16 +262,17 @@ async function handleSave(depensesTags, shouldOverwrite) {
saveError.value = null
try {
const response = await fetch('/api/save', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
// Mise à jour ciblée par ID : si la nouvelle extraction corrige la référence
// ou la date, c'est bien ce document qui est mis à jour, pas un doublon.
const response = await fetch(`/api/documents/${documentId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
source_file: extractedData.value.source_file,
data: extractedData.value.data,
depenses_tags: depensesTags,
overwrite: true // Toujours true en mode édition
depenses_tags: depensesTags
})
})