PAPERLESS_CONSUMER_ENABLE_BARCODES=true + DELETE_PAGES=true live auf mDock, parallel in m/paperless docker-compose.yml (Source-of-Truth) committet (siehe m/paperless commit 8c1ca3f). Neu: - infra/paperless/generate_separator.py — Code-128 PATCHT-Generator (uv inline-deps) - infra/paperless/separator-patchT.pdf — druckbare Trennseite - docs/strategy.md — neuer Abschnitt "Multi-page scan + automatic splitting" Test 2026-05-16: Stapel aus 3 Fake-Schreiben (2 + 1 + 1 Seiten) mit PATCHT-Separator dazwischen → 3 getrennte Paperless-Dokumente mit korrekten Seitenzahlen, Trennseiten entsorgt. Test-Dokumente wieder gelöscht. Closes: nichts (m schliesst Issues selbst — Label "done" via API)
96 lines
2.8 KiB
Python
Executable File
96 lines
2.8 KiB
Python
Executable File
#!/usr/bin/env -S uv run --script
|
|
# /// script
|
|
# requires-python = ">=3.11"
|
|
# dependencies = [
|
|
# "reportlab>=4.0",
|
|
# "python-barcode>=0.15",
|
|
# ]
|
|
# ///
|
|
"""Generate a Paperless-ngx separator page (PATCHT Code-128 barcode).
|
|
|
|
Run: ./generate_separator.py [out.pdf]
|
|
Default output: separator-patchT.pdf next to this script.
|
|
|
|
m prints the resulting PDF and lays one sheet between each document
|
|
in a multi-letter scan stack. Paperless-ngx (with
|
|
PAPERLESS_CONSUMER_ENABLE_BARCODES=true) detects the barcode and
|
|
splits the consumed PDF into separate documents.
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from barcode import Code128
|
|
from barcode.writer import ImageWriter
|
|
from reportlab.lib.pagesizes import A4
|
|
from reportlab.lib.units import cm
|
|
from reportlab.pdfgen import canvas
|
|
|
|
SEPARATOR_STRING = "PATCHT"
|
|
|
|
|
|
def main(out_path: Path) -> None:
|
|
page_w, page_h = A4
|
|
|
|
# Render barcode to a temporary PNG (reportlab needs an image source).
|
|
tmp_png = out_path.with_suffix(".tmp")
|
|
barcode = Code128(SEPARATOR_STRING, writer=ImageWriter())
|
|
barcode_path = barcode.save(
|
|
str(tmp_png),
|
|
options={
|
|
"module_width": 0.6, # mm per bar — bigger = easier OCR detection
|
|
"module_height": 30.0, # mm tall
|
|
"font_size": 14,
|
|
"text_distance": 5,
|
|
"quiet_zone": 8,
|
|
"write_text": True,
|
|
},
|
|
)
|
|
|
|
c = canvas.Canvas(str(out_path), pagesize=A4)
|
|
|
|
# Header
|
|
c.setFont("Helvetica-Bold", 36)
|
|
c.drawCentredString(page_w / 2, page_h - 4 * cm, "SEPARATOR")
|
|
c.setFont("Helvetica", 14)
|
|
c.drawCentredString(page_w / 2, page_h - 5 * cm,
|
|
"Zwischen zwei Dokumente legen — Paperless splittet hier.")
|
|
|
|
# Big crosshair for easy alignment when scanning
|
|
c.setLineWidth(1)
|
|
c.setStrokeGray(0.7)
|
|
c.line(page_w / 2 - 4 * cm, page_h - 6 * cm, page_w / 2 + 4 * cm, page_h - 6 * cm)
|
|
|
|
# Barcode — large, centred
|
|
img_w, img_h = 14 * cm, 5 * cm
|
|
c.drawImage(
|
|
barcode_path,
|
|
(page_w - img_w) / 2,
|
|
(page_h - img_h) / 2 - 1 * cm,
|
|
width=img_w,
|
|
height=img_h,
|
|
preserveAspectRatio=True,
|
|
mask="auto",
|
|
)
|
|
|
|
# Footer
|
|
c.setFont("Helvetica", 10)
|
|
c.setFillGray(0.3)
|
|
c.drawCentredString(page_w / 2, 4 * cm,
|
|
f"Code-128 · {SEPARATOR_STRING} · Paperless-ngx Barcode-Splitter")
|
|
c.drawCentredString(page_w / 2, 3 * cm,
|
|
"Detection: PAPERLESS_CONSUMER_ENABLE_BARCODES=true")
|
|
c.drawCentredString(page_w / 2, 2.4 * cm,
|
|
"Generator: infra/paperless/generate_separator.py (mDMS)")
|
|
|
|
c.showPage()
|
|
c.save()
|
|
|
|
Path(barcode_path).unlink(missing_ok=True)
|
|
print(f"wrote {out_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
out = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(__file__).parent / "separator-patchT.pdf"
|
|
main(out)
|