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):
|
||||
"""Standard-Fließtext mit Zeilenabstand."""
|
||||
"""Standard-Fließtext — Zeilenabstand kommt vom Style."""
|
||||
return make_paragraph(text, bold=bold, italic=italic,
|
||||
space_before=SP_BODY_BEFORE, space_after=SP_BODY_AFTER,
|
||||
line_spacing=LINE_SPACING)
|
||||
space_before=SP_BODY_BEFORE, space_after=SP_BODY_AFTER)
|
||||
|
||||
|
||||
def make_empty():
|
||||
@@ -284,11 +283,18 @@ def generate_angebot(data: dict, output_path: str):
|
||||
}
|
||||
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:
|
||||
if "Hannover" in (run.text or ""):
|
||||
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 ===
|
||||
angebotsnummer = data.get("angebotsnummer")
|
||||
@@ -405,6 +411,19 @@ def generate_angebot(data: dict, output_path: str):
|
||||
]):
|
||||
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
|
||||
if data.get("berater"):
|
||||
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_body(data["berater"]))
|
||||
|
||||
# V&S Qualitätsversprechen
|
||||
# V&S Qualitätsversprechen (Originaltext aus Referenz-Angeboten)
|
||||
kunde_formal = kunde.get("firma_formal", kunde["firma"])
|
||||
kunde_firma = kunde["firma"]
|
||||
laufzeit = data.get("laufzeit", "12 Monate")
|
||||
|
||||
new_elements.append(make_empty())
|
||||
new_elements.append(make_heading("V&S Qualitätsversprechen"))
|
||||
new_elements.append(make_empty())
|
||||
new_elements.append(make_body(
|
||||
f"Sollte {kunde_formal} mit den Ergebnissen des Projektes nicht zufrieden sein, "
|
||||
f"so entscheidet {kunde_formal} einen Monat rückwirkend über das Monats-Honorar "
|
||||
f"– bis hin zu einem Honorar von 0 EUR."
|
||||
f"Die Zufriedenheit der {kunde_firma} hat für uns höchste Priorität."
|
||||
))
|
||||
new_elements.append(make_body(
|
||||
f"Geplant ist eine Begleitung über {laufzeit}. Allerdings kann {kunde_formal} "
|
||||
f"das gemeinsame Vorhaben jederzeit beenden."
|
||||
f"Sollte unser Klient mit den Ergebnissen der Zusammenarbeit nicht zufrieden sein, so "
|
||||
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
|
||||
@@ -439,8 +461,29 @@ def generate_angebot(data: dict, output_path: str):
|
||||
insert_point = elem
|
||||
|
||||
# === 7. SCHLUSSBESTIMMUNGEN AKTUALISIEREN ===
|
||||
# Die existierenden Schlussbestimmungen sind schon im Dokument (wurden nicht gelöscht)
|
||||
# Wir müssen nur "Der Klient" durch den Kundennamen ersetzen
|
||||
# Schlussbestimmung-Heading formatieren (kommt aus Template als "Normal (Web)")
|
||||
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:
|
||||
if p.text.startswith("Der Klient"):
|
||||
firma_ref = kunde_formal
|
||||
|
||||
Reference in New Issue
Block a user