Zurück zur Startseite
Leistungen

Backend Engineering, Produkt

Branche

B2B-Marktplatz

Jahr

2022-2024

Sechzehn Vertragstypen, generiert aus verifizierten Daten

Ein Vertrag verließ einen B2B-Marktplatz mit '[FIRMENNAME]' in der Kopfzeile. Er hatte den üblichen Weg genommen: eine von sechzehn Word-Vorlagen auf einem Netzlaufwerk, von Hand ausgefüllt, an die Rechtsabteilung gemailt, korrigiert, exportiert, noch einmal gemailt zur Unterschrift. Drei Werktage pro Vertrag. Jeder fünfte mit falschem Namen, alter Zahlungsfrist oder fehlender Klausel.

DIE HERAUSFORDERUNG

Sechzehn Vorlagen, vier Haftungsobergrenzen

Jede Word-Vorlage hatte gelb markierte Platzhalterfelder, die ein Account Manager von Hand überschrieb, meist ausgehend vom vorherigen Vertrag. So wanderte ein Firmenname aus der Vereinbarung eines Kunden in die des nächsten, und so kam ein Platzhalter unbemerkt in eine Kopfzeile. Die Klauseln drifteten genauso, nur langsamer. Vier der sechzehn Vorlagen nannten unterschiedliche Haftungsobergrenzen. Wenn die Rechtsabteilung eine Klausel änderte, musste jemand alle sechzehn Dateien öffnen und den neuen Text einfügen; drei Monate nach einer solchen Änderung stand in zwei Vorlagen noch die alte Fassung, und der Erste, dem es auffiel, war der Anwalt eines Kunden. Nichts war versioniert, also konnte niemand sagen, aus welchem Text ein unterschriebener Vertrag entstanden war.

Der schnellste Weg, Fehler aus einem Vertrag zu entfernen, ist den Schritt zu entfernen, in dem ein Mensch die Daten tippt.

DIE LÖSUNG

Vorlagen in der Datenbank, Daten aus dem Datensatz

Der naheliegende Kauf wäre eine Vertragsplattform wie PandaDoc oder DocuSign CLM gewesen. Die lösen Freigabeketten, E-Signaturen und CRM-Abgleich; das Problem hier war ein Mensch, der Daten abtippte, die schon existierten. Ich habe sie verworfen: wegen der monatlichen Kosten, weil Verträge den Server verlassen hätten, und wegen des API-Mappings zwischen ihren Feldern und dem Django-Modell. Stattdessen wurde jeder Vertragstyp ein Django-Template, gespeichert als Datenbanksatz mit typisierten Variablen. Generieren liest Firmenname, Adresse, vereinbarte Konditionen und Preise aus dem Listing-Datensatz, validiert jede Variable, rendert HTML und schreibt das PDF mit WeasyPrint. Der Kompromiss heißt Verantwortung: Die Rechtsabteilung bearbeitet Vorlagen im Django-Admin statt in Word, und das Team pflegt die Engine.

Der Generierungspfad: verifizierte Daten rein, validierter Kontext, HTML zu PDF, und ein Datensatz, der festhält, welche Klauselversionen und welchen Hash das Dokument hat:

Python
class ContractGenerator:
    def generate(self, listing, template_type):
        """Generate a contract PDF from verified data."""
        template = ContractTemplate.objects.get(
            type=template_type,
            is_active=True,
        )

        # Pull variables from verified database records
        context = {
            'company': listing.company,
            'address': listing.company.billing_address,
            'terms': listing.agreed_terms,
            'pricing': listing.pricing_schedule,
            'clauses': template.get_active_clauses(),
            'generated_at': timezone.now(),
        }

        # Validate all variables before rendering
        template.validate_context(context)

        # Render HTML → PDF
        html = render_to_string(
            template.django_template_path,
            context,
        )
        pdf = weasyprint.HTML(string=html).write_pdf()

        # Store with audit trail
        return Contract.objects.create(
            listing=listing,
            template_version=template.version,
            clause_versions=template.clause_version_map(),
            pdf_hash=hashlib.sha256(pdf).hexdigest(),
            pdf_file=ContentFile(pdf, name=f'{listing.slug}.pdf'),
        )

Einen Vertrag generieren, dann die Basis ändern

Wähle einen Vertragstyp und generiere. Die Variablen kommen aus den Feldern, nicht aus Tippen im Dokument; leere eines, und die Vorschau zeigt den Platzhalter, der einmal rausging, und die Generierung stoppt. Dann drück das Legal-Update: §7 ändert sich in der Basis, und jeder Typ in der Leiste übernimmt es, egal welcher gerade ausgewählt ist.

Dienstleistungsvertrag

Nr. 260928-1947 · Datum 2026-09-28

Zwischen Halden Logistics GmbH und dem Marktplatz.

  1. §1LeistungsumfangTyp · v1

    Der Marktplatz erbringt für Halden Logistics GmbH die Leistung Inseratsverwaltung für eine Laufzeit von 12 Monaten.

  2. §2GebührenTyp · v1

    Halden Logistics GmbH zahlt eine monatliche Gebühr von 1.500 €, fällig 30 Tage netto.

  3. §3LaufzeitBasis · v1

    Dieser Vertrag läuft zwölf Monate und verlängert sich, sofern er nicht gekündigt wird.

  4. §4VertraulichkeitBasis · v1

    Beide Parteien behandeln die Geschäftsinformationen der anderen vertraulich.

  5. §5DatenschutzBasis · v1

    Personenbezogene Daten werden gemäß der Auftragsverarbeitungsvereinbarung in Anlage 1 verarbeitet.

  6. §6Geistiges EigentumBasis · v1

    Von Halden Logistics GmbH hochgeladene Inhalte bleiben Eigentum von Halden Logistics GmbH.

  7. §7HaftungBasis · v1

    Die Haftung ist auf die in den zwölf Monaten vor dem Anspruch gezahlten Gebühren begrenzt.

  8. §8GewährleistungBasis · v1

    Die Leistungen werden mit der Sorgfalt eines ordentlichen Kaufmanns erbracht.

  9. §9KündigungBasis · v1

    Jede Partei kann mit einer Frist von drei Monaten zum Ende einer Laufzeit kündigen.

  10. §10Höhere GewaltBasis · v1

    Keine Partei haftet für Verzögerungen durch Ereignisse außerhalb ihrer Kontrolle.

  11. §11Anwendbares RechtBasis · v1

    Dieser Vertrag unterliegt österreichischem Recht.

  12. §12SchlussbestimmungenBasis · v1

    Änderungen bedürfen der Schriftform. Unwirksame Klauseln berühren den Rest nicht.

Noch nicht generiert. Generieren zeichnet die Klauselversionen und den Dokument-Hash auf.

16 Vertragstypen erweitern die Basis

  • Dienstleistungsvertrag§7 v1
  • Geheimhaltungsvereinbarung§7 v1
  • Wartungsvertrag§7 v1
  • Typ 04§7 v1
  • Typ 05§7 v1
  • Typ 06§7 v1
  • Typ 07§7 v1
  • Typ 08§7 v1
  • Typ 09§7 v1
  • Typ 10§7 v1
  • Typ 11§7 v1
  • Typ 12§7 v1
  • Typ 13§7 v1
  • Typ 14§7 v1
  • Typ 15§7 v1
  • Typ 16§7 v1
Variablen injiziert
5 / 5
Klauseln aus der Basis
10 / 12
Vom Typ überschrieben
2
Typen auf §7 v2
0 / 16

Das Basis-Template. Jeder Vertragstyp erweitert es und überschreibt ein, zwei Blöcke; §3 bis §12 kommen aus dem gemeinsamen Klauselsatz:

HTML
{# base_service_agreement.html #}
{# All 16 contract types inherit from this base #}

<p class="doc-title">Service Agreement</p>
<p>Between {{ company.name }} and the Marketplace.</p>

{% block scope %}
  <h2>§1 Scope of Services</h2>
  <p>{{ terms.scope_description }}</p>
{% endblock %}

{% block compensation %}
  <h2>§2 Compensation</h2>
  <p>Monthly rate: €{{ pricing.monthly_rate|floatformat:2 }}</p>
{% endblock %}

{# §3-§12: shared standard clauses, one file for all types #}
{% for clause in clauses %}
  <h2>§{{ clause.number }} {{ clause.title }}</h2>
  {{ clause.body|safe }}
{% endfor %}
DAS ERGEBNIS

Verträge wurden ein Button im Inserat

Account Manager generieren Verträge heute aus dem Inserat, an dem sie gerade arbeiten, und gehen zurück zum Kunden statt zu Word. Die Rechtsabteilung prüft eine Vorlagenänderung einmal und weiß, dass sie überall gilt; aus vier Haftungsobergrenzen ist wieder eine Klausel geworden. Ein Platzhalter kann keine Kopfzeile mehr erreichen, weil es keine Platzhalter gibt, nur Variablen, die entweder validieren oder den Lauf stoppen. Jedes PDF trägt seine Klauselversionen und einen Hash, also ist die Frage, welche Formulierung ein Kunde vor sechs Monaten unterschrieben hat, ein Lookup und keine E-Mail-Suche. Aus Tagen Durchlaufzeit wurden Sekunden.

WICHTIGE KENNZAHLEN

< 2sGenerierungszeit pro Vertrag
0%Feldfehler seit Einführung
40+Verträge pro Woche
KUNDENSTIMME

Verträge haben früher einen guten Teil meines Montags gefressen. Jetzt öffne ich das Inserat, wähle den Typ, prüfe die Felder, die das System gezogen hat, und das PDF ist da. Ich habe seitdem keinen Firmennamen mehr in einen Vertrag getippt, und ich könnte es auch gar nicht.

Senior Account Manager

B2B-Marktplatz, Vertrieb

FÜR DEIN PROJEKT

  • Wann das passt

    Du stellst denselben Dokumenttyp immer wieder aus Daten aus, die du schon speicherst, und die Fehler entstehen beim Abtippen: Verträge, Angebote, Auftragsbestätigungen. Das Signal ist ein Platzhalter oder ein veralteter Wert, der beim Kunden ankommt.

  • Was du prüfen solltest

    Wo die Daten heute liegen. Wenn Firma, Konditionen und Preise in einem Datensatz stehen, können Templates sie lesen; wenn sie im Kopf des Account Managers liegen, ist das die erste Baustelle. Dann zähle die Kopien jeder Klausel über deine Vorlagen hinweg. Hier waren es sechzehn.

  • Was es braucht

    Eine Backend-Entwicklerin oder einen -Entwickler für die Engine, eine verantwortliche Person in der Rechtsabteilung, die Vorlagen im Admin statt in Word bearbeitet, und einen Prüfschritt für Vorlagenversionen. Keine Lizenzkosten, keine Daten, die den Server verlassen, aber der Code gehört dir, samt Pflege.

FAQ

TECHNOLOGIE-STACK

Django
Python
PostgreSQL

Seit mittlerweile 10 Jahren arbeiten wir immer wieder gerne mit Daniel zusammen. Wir schätzen dabei sehr seine schnellen Reaktionszeiten rund um die Uhr und sein Allroundwissen. Egal ob Serverkonfigurationen oder Programmierungen, er hat immer die passende Lösung.

Manuel Kasbarian - Geschäftsführer, SophistiX

Tritt in die Fußstapfen von Manuel und erwecke deine Vision zum Leben.

Schreibe mirSchreibe mir