Skip unchanged Excel report uploads
This commit is contained in:
parent
ddae04c585
commit
5d81016ece
|
|
@ -64,7 +64,9 @@ damit interne Dokumentdaten nicht unbeabsichtigt über einen Proxy laufen.
|
||||||
SHA-256-Prüfsummen und SQLite verhindern, dass erfolgreich verarbeitete Inhalte
|
SHA-256-Prüfsummen und SQLite verhindern, dass erfolgreich verarbeitete Inhalte
|
||||||
erneut verarbeitet werden. Bestehende Zieldateien werden nicht überschrieben; bei
|
erneut verarbeitet werden. Bestehende Zieldateien werden nicht überschrieben; bei
|
||||||
Kollisionen wird `_02`, `_03` usw. ergänzt. Eine Prozesssperre verhindert parallele
|
Kollisionen wird `_02`, `_03` usw. ergänzt. Eine Prozesssperre verhindert parallele
|
||||||
Läufe auf derselben Installation.
|
Läufe auf derselben Installation. Entsteht während eines Laufs kein neuer
|
||||||
|
Protokolleintrag, wird `protokoll.xlsx` weder lokal neu erzeugt noch erneut zu
|
||||||
|
Nextcloud hochgeladen.
|
||||||
|
|
||||||
## Installation auf einer Linux-VM
|
## Installation auf einer Linux-VM
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "orc-renaming"
|
name = "orc-renaming"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
description = "Lokale, datenschutzfreundliche Benennung gescannter PDF-Dokumente"
|
description = "Lokale, datenschutzfreundliche Benennung gescannter PDF-Dokumente"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
"""Lokale Dokumentklassifikation und PDF-Benennung."""
|
"""Lokale Dokumentklassifikation und PDF-Benennung."""
|
||||||
|
|
||||||
__version__ = "0.4.0"
|
__version__ = "0.4.1"
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,12 @@ class Ledger:
|
||||||
).fetchone()
|
).fetchone()
|
||||||
return row is not None
|
return row is not None
|
||||||
|
|
||||||
|
def entry_count(self) -> int:
|
||||||
|
row = self.connection.execute(
|
||||||
|
"SELECT COUNT(*) AS count FROM processing_log"
|
||||||
|
).fetchone()
|
||||||
|
return int(row["count"])
|
||||||
|
|
||||||
def add(self, record: ProcessingRecord) -> None:
|
def add(self, record: ProcessingRecord) -> None:
|
||||||
values = record.model_dump(mode="json")
|
values = record.model_dump(mode="json")
|
||||||
values["evidence"] = json.dumps(
|
values["evidence"] = json.dumps(
|
||||||
|
|
|
||||||
|
|
@ -301,6 +301,7 @@ class Pipeline:
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def run(self) -> dict[str, int]:
|
def run(self) -> dict[str, int]:
|
||||||
|
entries_before_run = self.ledger.entry_count()
|
||||||
upload_report = (
|
upload_report = (
|
||||||
not self.config.processing.dry_run
|
not self.config.processing.dry_run
|
||||||
or self.config.processing.upload_excel_in_dry_run
|
or self.config.processing.upload_excel_in_dry_run
|
||||||
|
|
@ -342,6 +343,12 @@ class Pipeline:
|
||||||
status = "error"
|
status = "error"
|
||||||
counters[status] = counters.get(status, 0) + 1
|
counters[status] = counters.get(status, 0) + 1
|
||||||
|
|
||||||
|
if self.ledger.entry_count() == entries_before_run:
|
||||||
|
LOGGER.info(
|
||||||
|
"Protokoll unverändert; Excel-Export und Nextcloud-Upload übersprungen"
|
||||||
|
)
|
||||||
|
return counters
|
||||||
|
|
||||||
excel_path = (
|
excel_path = (
|
||||||
self.config.processing.state_directory
|
self.config.processing.state_directory
|
||||||
/ self.config.processing.excel_filename
|
/ self.config.processing.excel_filename
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,12 @@ from datetime import date
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import orc_renaming.pipeline as pipeline_module
|
import orc_renaming.pipeline as pipeline_module
|
||||||
from orc_renaming.models import DocumentScope, DocumentType, ExtractionResult
|
from orc_renaming.models import (
|
||||||
|
DocumentScope,
|
||||||
|
DocumentType,
|
||||||
|
ExtractionResult,
|
||||||
|
ProcessingRecord,
|
||||||
|
)
|
||||||
from orc_renaming.normalize import result_is_complete
|
from orc_renaming.normalize import result_is_complete
|
||||||
from orc_renaming.pipeline import Pipeline
|
from orc_renaming.pipeline import Pipeline
|
||||||
from orc_renaming.webdav import RemoteFile
|
from orc_renaming.webdav import RemoteFile
|
||||||
|
|
@ -111,6 +116,44 @@ def test_live_run_uploads_pdf_report_and_archives(config, monkeypatch) -> None:
|
||||||
assert config.nextcloud.review_folder in folders
|
assert config.nextcloud.review_folder in folders
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_run_does_not_write_or_upload_report(config, monkeypatch) -> None:
|
||||||
|
_prepare(monkeypatch)
|
||||||
|
|
||||||
|
with Pipeline(config) as pipeline:
|
||||||
|
pipeline.webdav.list_pdfs = lambda _folder: []
|
||||||
|
counters = pipeline.run()
|
||||||
|
uploads = list(pipeline.webdav.uploads)
|
||||||
|
|
||||||
|
assert counters == {}
|
||||||
|
assert uploads == []
|
||||||
|
assert not (config.processing.state_directory / "protokoll.xlsx").exists()
|
||||||
|
|
||||||
|
|
||||||
|
def test_skipped_files_do_not_rewrite_report(config, monkeypatch) -> None:
|
||||||
|
_prepare(monkeypatch)
|
||||||
|
report_path = config.processing.state_directory / "protokoll.xlsx"
|
||||||
|
|
||||||
|
with Pipeline(config) as pipeline:
|
||||||
|
pipeline.ledger.add(
|
||||||
|
ProcessingRecord(
|
||||||
|
remote_path="/Scanner/Eingang/scan001.pdf",
|
||||||
|
original_name="scan001.pdf",
|
||||||
|
checksum="abc123",
|
||||||
|
status="success",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
pipeline.ledger.export_xlsx(report_path)
|
||||||
|
report_before = report_path.read_bytes()
|
||||||
|
|
||||||
|
counters = pipeline.run()
|
||||||
|
uploads = list(pipeline.webdav.uploads)
|
||||||
|
report_after = report_path.read_bytes()
|
||||||
|
|
||||||
|
assert counters == {"skipped": 1}
|
||||||
|
assert uploads == []
|
||||||
|
assert report_after == report_before
|
||||||
|
|
||||||
|
|
||||||
def test_ollama_fallback_is_only_used_after_incomplete_primary(
|
def test_ollama_fallback_is_only_used_after_incomplete_primary(
|
||||||
config, monkeypatch
|
config, monkeypatch
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue