Keine Zentrierung für Tätigkeiten. Doppeltes Datum anzeigen.

This commit is contained in:
Rob committed 2026-06-30 10:52:45 +02:00
1 parent 87f8150bd3
commit 8fde588b8f
3 files changed
+68 -73

No files matched your search

+68 -73
View File
@@ -102,10 +102,10 @@ def _scan_template_fields(
template_path: Path, template_path: Path,
mapping: list[OutputMapping], mapping: list[OutputMapping],
fontsize: float, fontsize: float,
) -> dict[str, dict]: ) -> dict[str, list[dict]]:
""" """
Scannt ALLE Seiten des PDF-Templates nach _Field-Platzhaltern. Scannt ALLE Seiten des PDF-Templates nach _Field-Platzhaltern.
Rückgabe: dict[pdf_field] → {source_field, page_num, rect, fontsize, fontname, ...} Rückgabe: dict[pdf_field] → Liste von {source_field, page_num, rect, fontsize, fontname, ...}
Felder mit pdf_field=None werden übersprungen. Felder mit pdf_field=None werden übersprungen.
""" """
doc = fitz.open(template_path) doc = fitz.open(template_path)
@@ -116,26 +116,23 @@ def _scan_template_fields(
if m.pdf_field is not None: if m.pdf_field is not None:
pdf_to_source[m.pdf_field] = m.source_field pdf_to_source[m.pdf_field] = m.source_field
field_info: dict[str, dict] = {} field_info: dict[str, list[dict]] = {}
# Per search_for die Rechtecke aller PDF-Feld-Marker finden (alle Seiten) # Alle Vorkommen aller PDF-Feld-Marker finden (alle Seiten)
for pdf_field, source_field in pdf_to_source.items(): for pdf_field, source_field in pdf_to_source.items():
found_any = False occurrences: list[dict] = []
for page_num in range(doc.page_count): for page_num in range(doc.page_count):
page = doc[page_num] page = doc[page_num]
found = page.search_for(pdf_field) found = page.search_for(pdf_field)
if found: for rect in found:
field_info[pdf_field] = { occurrences.append({
"source_field": source_field, "source_field": source_field,
"page_num": page_num, "page_num": page_num,
"rect": found[0], "rect": rect,
"fontsize": fontsize, "fontsize": fontsize,
"fontname": "helv", "fontname": "helv",
} })
found_any = True field_info[pdf_field] = occurrences
break # erstes Vorkommen (seitenübergreifend)
if not found_any:
field_info[pdf_field] = None # nicht gefunden
doc.close() doc.close()
return field_info return field_info
@@ -150,7 +147,7 @@ def _fill_pdf_pages(
record: EmployeeRecord, record: EmployeeRecord,
employee_name: str, employee_name: str,
mapping: list[OutputMapping], mapping: list[OutputMapping],
field_info: dict[str, dict], field_info: dict[str, list[dict]],
fontsize: float, fontsize: float,
) -> None: ) -> None:
"""Befüllt alle Template-Seiten: redacted _Field-Platzhalter und fügt echte Daten ein.""" """Befüllt alle Template-Seiten: redacted _Field-Platzhalter und fügt echte Daten ein."""
@@ -162,76 +159,74 @@ def _fill_pdf_pages(
if m.pdf_field is None: if m.pdf_field is None:
continue continue
info = field_info.get(m.pdf_field) occurrences = field_info.get(m.pdf_field, [])
if info is None: if not occurrences:
continue # Feld nicht im Template gefunden continue # Feld nicht im Template gefunden
page_num = info["page_num"]
if page_num >= len(pages):
continue
page = pages[page_num]
rect = info["rect"]
value = _get_field_value(record, employee_name, m.source_field) value = _get_field_value(record, employee_name, m.source_field)
formatted = _format_value(value, m.format) formatted = _format_value(value, m.format)
# Platzhalter immer redacten, auch wenn kein Wert zum Einsetzen da ist # Jedes Vorkommen des Feldes im PDF befüllen
page.add_redact_annot(rect) for info in occurrences:
page.apply_redactions() page_num = info["page_num"]
if page_num >= len(pages):
if not formatted:
continue
# Mehrzeilige Felder: Zeilenweise per insert_text schreiben
if m.pdf_field in MULTILINE_FIELDS:
# Doppelte Leerzeilen entfernen
clean_text = "\n".join(
line for line in formatted.split("\n") if line.strip()
)
if not clean_text:
continue continue
# Zeilenweise mit automatischem Umbruch schreiben page = pages[page_num]
lines = clean_text.split("\n") rect = info["rect"]
line_spacing = fontsize * 1.2 # Zeilenabstand
# Zuerst alle Ausgabezeilen sammeln, um Gesamthöhe zu berechnen # Platzhalter redacten
output_lines: list[str] = [] page.add_redact_annot(rect)
for line in lines: page.apply_redactions()
max_width = TEXTBOX_WIDTH_PT
words = line.split(" ")
current_line = ""
for word in words:
test_line = current_line + (" " if current_line else "") + word
text_width = fitz.get_text_length(test_line, fontname="helv", fontsize=fontsize)
if text_width <= max_width or not current_line:
current_line = test_line
else:
output_lines.append(current_line)
current_line = word
if current_line:
output_lines.append(current_line)
# Textblock oben beginnend schreiben if not formatted:
y = rect.y0 + fontsize continue
for current_line in output_lines: # Mehrzeilige Felder: Zeilenweise per insert_text schreiben
page.insert_text( if m.pdf_field in MULTILINE_FIELDS:
(rect.x0, y), current_line, # ... (unverändert)
fontname="helv", fontsize=fontsize, clean_text = "\n".join(
line for line in formatted.split("\n") if line.strip()
)
if not clean_text:
continue
lines = clean_text.split("\n")
line_spacing = fontsize * 1.2
output_lines: list[str] = []
for line in lines:
max_width = TEXTBOX_WIDTH_PT
words = line.split(" ")
current_line = ""
for word in words:
test_line = current_line + (" " if current_line else "") + word
text_width = fitz.get_text_length(test_line, fontname="helv", fontsize=fontsize)
if text_width <= max_width or not current_line:
current_line = test_line
else:
output_lines.append(current_line)
current_line = word
if current_line:
output_lines.append(current_line)
y = rect.y0 + fontsize
for current_line in output_lines:
page.insert_text(
(rect.x0, y), current_line,
fontname="helv", fontsize=fontsize,
)
y += line_spacing
else:
# Einzeilige Felder: vertikal zentriert platzieren
mid_y = (rect.y0 + rect.y1) / 2
baseline_y = mid_y + fontsize * 0.35
page.insert_text(
(rect.x0, baseline_y),
formatted,
fontname="helv",
fontsize=fontsize,
) )
y += line_spacing
else:
# Einzeilige Felder: vertikal zentriert platzieren
mid_y = (rect.y0 + rect.y1) / 2
baseline_y = mid_y + fontsize * 0.35
page.insert_text(
(rect.x0, baseline_y),
formatted,
fontname="helv",
fontsize=fontsize,
)
# ───────────────────────────────────────────── # ─────────────────────────────────────────────
Binary file not shown.
Binary file not shown.