diff --git a/kim-angebot/scripts/generate_angebot.py b/kim-angebot/scripts/generate_angebot.py index 6fa90df..377eb1d 100644 --- a/kim-angebot/scripts/generate_angebot.py +++ b/kim-angebot/scripts/generate_angebot.py @@ -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