fix: Style-Namen repariert, Qualitätsversprechen & Investitionslogik verbessert
- Kaputte Style-Namen (Umlaute gefehlt) korrigiert - Hannover-Datum: Fix für mehrzeilige Runs - Neue optionale Sektion: Erwartungshaltung & Investitionslogik - Qualitätsversprechen näher am Original-Wortlaut - Schlussbestimmung-Heading wird korrekt blau formatiert Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -154,10 +154,9 @@ def make_heading(text):
|
|||||||
|
|
||||||
|
|
||||||
def make_body(text, bold=False, italic=False):
|
def make_body(text, bold=False, italic=False):
|
||||||
"""Standard-Fließtext mit Zeilenabstand."""
|
"""Standard-Fließtext — Zeilenabstand kommt vom Style."""
|
||||||
return make_paragraph(text, bold=bold, italic=italic,
|
return make_paragraph(text, bold=bold, italic=italic,
|
||||||
space_before=SP_BODY_BEFORE, space_after=SP_BODY_AFTER,
|
space_before=SP_BODY_BEFORE, space_after=SP_BODY_AFTER)
|
||||||
line_spacing=LINE_SPACING)
|
|
||||||
|
|
||||||
|
|
||||||
def make_empty():
|
def make_empty():
|
||||||
@@ -284,11 +283,18 @@ def generate_angebot(data: dict, output_path: str):
|
|||||||
}
|
}
|
||||||
datum = f"{now.day}. {monatsnamen[now.month]} {now.year}"
|
datum = f"{now.day}. {monatsnamen[now.month]} {now.year}"
|
||||||
|
|
||||||
# Find the text run with "Hannover" in paragraph 0
|
# Find the text run with "Hannover" in paragraph 0 and replace date
|
||||||
|
# The date may span multiple runs, so clear all runs after "Hannover" too
|
||||||
|
found_hannover = False
|
||||||
for run in p0.runs:
|
for run in p0.runs:
|
||||||
if "Hannover" in (run.text or ""):
|
if "Hannover" in (run.text or ""):
|
||||||
run.text = f" Hannover, {datum}"
|
run.text = f" Hannover, {datum}"
|
||||||
break
|
found_hannover = True
|
||||||
|
continue
|
||||||
|
if found_hannover and run.text and not run._element.findall('.//' + qn('w:drawing')):
|
||||||
|
# Clear remaining text runs after Hannover (old date fragments)
|
||||||
|
# but don't touch runs with images
|
||||||
|
run.text = ""
|
||||||
|
|
||||||
# === 3. AKTENZEICHEN AKTUALISIEREN ===
|
# === 3. AKTENZEICHEN AKTUALISIEREN ===
|
||||||
angebotsnummer = data.get("angebotsnummer")
|
angebotsnummer = data.get("angebotsnummer")
|
||||||
@@ -405,6 +411,19 @@ def generate_angebot(data: dict, output_path: str):
|
|||||||
]):
|
]):
|
||||||
new_elements.append(make_body(line))
|
new_elements.append(make_body(line))
|
||||||
|
|
||||||
|
# Erwartungshaltung & Investitionslogik (optional)
|
||||||
|
if data.get("investitionslogik"):
|
||||||
|
new_elements.append(make_empty())
|
||||||
|
il = data["investitionslogik"]
|
||||||
|
new_elements.append(make_heading(il.get("ueberschrift", "Erwartungshaltung & Investitionslogik")))
|
||||||
|
new_elements.append(make_empty())
|
||||||
|
for block in il.get("inhalt", []):
|
||||||
|
typ = block["typ"]
|
||||||
|
if typ == "text":
|
||||||
|
new_elements.append(make_body(block["text"]))
|
||||||
|
elif typ == "text_bold":
|
||||||
|
new_elements.append(make_body(block["text"], bold=True))
|
||||||
|
|
||||||
# Durchführung
|
# Durchführung
|
||||||
if data.get("berater"):
|
if data.get("berater"):
|
||||||
new_elements.append(make_empty())
|
new_elements.append(make_empty())
|
||||||
@@ -412,21 +431,24 @@ def generate_angebot(data: dict, output_path: str):
|
|||||||
new_elements.append(make_empty())
|
new_elements.append(make_empty())
|
||||||
new_elements.append(make_body(data["berater"]))
|
new_elements.append(make_body(data["berater"]))
|
||||||
|
|
||||||
# V&S Qualitätsversprechen
|
# V&S Qualitätsversprechen (Originaltext aus Referenz-Angeboten)
|
||||||
kunde_formal = kunde.get("firma_formal", kunde["firma"])
|
kunde_formal = kunde.get("firma_formal", kunde["firma"])
|
||||||
|
kunde_firma = kunde["firma"]
|
||||||
laufzeit = data.get("laufzeit", "12 Monate")
|
laufzeit = data.get("laufzeit", "12 Monate")
|
||||||
|
|
||||||
new_elements.append(make_empty())
|
new_elements.append(make_empty())
|
||||||
new_elements.append(make_heading("V&S Qualitätsversprechen"))
|
new_elements.append(make_heading("V&S Qualitätsversprechen"))
|
||||||
new_elements.append(make_empty())
|
new_elements.append(make_empty())
|
||||||
new_elements.append(make_body(
|
new_elements.append(make_body(
|
||||||
f"Sollte {kunde_formal} mit den Ergebnissen des Projektes nicht zufrieden sein, "
|
f"Die Zufriedenheit der {kunde_firma} hat für uns höchste Priorität."
|
||||||
f"so entscheidet {kunde_formal} einen Monat rückwirkend über das Monats-Honorar "
|
|
||||||
f"– bis hin zu einem Honorar von 0 EUR."
|
|
||||||
))
|
))
|
||||||
new_elements.append(make_body(
|
new_elements.append(make_body(
|
||||||
f"Geplant ist eine Begleitung über {laufzeit}. Allerdings kann {kunde_formal} "
|
f"Sollte unser Klient mit den Ergebnissen der Zusammenarbeit nicht zufrieden sein, so "
|
||||||
f"das gemeinsame Vorhaben jederzeit beenden."
|
f"behält sie sich das Recht vor, das jeweilige Monats-Honorar rückwirkend anzupassen "
|
||||||
|
f"– bis hin zu einem Betrag von 0 EUR. Das KIM-Programm ist auf eine Laufzeit von "
|
||||||
|
f"zwölf Monaten ausgelegt. {kunde_firma} kann das Vorhaben jedoch jederzeit und ohne "
|
||||||
|
f"Angabe von Gründen beenden. Dieses Qualitätsversprechen spiegelt unseren Anspruch "
|
||||||
|
f"an Verbindlichkeit, Transparenz und partnerschaftliches Arbeiten wider."
|
||||||
))
|
))
|
||||||
|
|
||||||
# Leere Zeilen vor Schlussbestimmungen
|
# Leere Zeilen vor Schlussbestimmungen
|
||||||
@@ -439,8 +461,29 @@ def generate_angebot(data: dict, output_path: str):
|
|||||||
insert_point = elem
|
insert_point = elem
|
||||||
|
|
||||||
# === 7. SCHLUSSBESTIMMUNGEN AKTUALISIEREN ===
|
# === 7. SCHLUSSBESTIMMUNGEN AKTUALISIEREN ===
|
||||||
# Die existierenden Schlussbestimmungen sind schon im Dokument (wurden nicht gelöscht)
|
# Schlussbestimmung-Heading formatieren (kommt aus Template als "Normal (Web)")
|
||||||
# Wir müssen nur "Der Klient" durch den Kundennamen ersetzen
|
for p in doc.paragraphs:
|
||||||
|
if "Schlussbestimmung" in p.text and len(p.text.strip()) < 25:
|
||||||
|
# Heading-Formatierung anwenden (blau, Heading 2, 12pt)
|
||||||
|
for run in p.runs:
|
||||||
|
run.font.name = FONT_NAME
|
||||||
|
run.font.size = HEADING_SIZE
|
||||||
|
run.font.color.rgb = BLUE_HEADING
|
||||||
|
run.font.bold = True
|
||||||
|
# Spacing anpassen
|
||||||
|
pPr = p._element.find(qn('w:pPr'))
|
||||||
|
if pPr is None:
|
||||||
|
pPr = OxmlElement('w:pPr')
|
||||||
|
p._element.insert(0, pPr)
|
||||||
|
spacing = pPr.find(qn('w:spacing'))
|
||||||
|
if spacing is None:
|
||||||
|
spacing = OxmlElement('w:spacing')
|
||||||
|
pPr.append(spacing)
|
||||||
|
spacing.set(qn('w:before'), str(SP_HEADING_BEFORE))
|
||||||
|
spacing.set(qn('w:after'), str(SP_HEADING_AFTER))
|
||||||
|
break
|
||||||
|
|
||||||
|
# "Der Klient" durch den Kundennamen ersetzen
|
||||||
for p in doc.paragraphs:
|
for p in doc.paragraphs:
|
||||||
if p.text.startswith("Der Klient"):
|
if p.text.startswith("Der Klient"):
|
||||||
firma_ref = kunde_formal
|
firma_ref = kunde_formal
|
||||||
|
|||||||
Reference in New Issue
Block a user