Technisches Briefing

Rechnungs- & Kundensystem

tv-vermarktung.de  ·  ExtraTippS Deutschland GmbH  ·  Stand 06.07.2026

Dieses Dokument beschreibt den vollständigen Aufbau eines Rechnungs-, Mahnwesen- und DATEV-Exportsystems für tv-vermarktung.de. Datenbasis ist Airtable, Generierung läuft serverseitig auf Hetzner. Die Schritte sind sequenziell — Schritt 1 ist Voraussetzung für alle weiteren. Das PDF-Design (Schritt 2) ist bereits fertiggestellt und abgenommen.

INF

Infrastruktur & Credentials

KomponenteDetails
Airtable BaseappRz7oc24ZZa1bXB
Airtable TabelleLeads (Hauptdatenbasis)
ServerHetzner · 88.198.23.107 · SSH: ssh ubuntu@88.198.23.107
SMTPsmtp.ionos.de:587 · Absender: produktion@tv-vermarktung.de
BCC (alle Mails)produktion@tv-vermarktung.de
Airtable Tokenwird separat übergeben
SMTP Passwortwird separat übergeben

Firmendaten

tv-vermarktung.de — Eine Marke der ExtraTippS Deutschland GmbH
Siemensstraße 22a · 61130 Nidderau
Tel. 06187 20 32 961 · produktion@tv-vermarktung.de
USt.-ID: DE359807794 · StNr: 019 232 50024 · HRB 99039 Hanau
Bank: Sparkasse Oberhessen
IBAN: DE25 5185 0079 0027 1889 15 · BIC: HELADEF1FRI
1

Airtable vorbereiten

Neue Felder in Tabelle Leads

FeldnameTypZweck
Erweiterung1numberErweiterungsbetrag 1 (netto)
Erweiterung2numberErweiterungsbetrag 2 (netto)
VerlängerungnumberVerlängerungsbetrag 1 (netto)
Verlängerung2numberVerlängerungsbetrag 2 (netto)
RechnungsnummersingleLineTextgeneriert, Format JJMMKWNR
RechnungsdatumdateDatum der Rechnungsstellung
ZahlungszieldateFreitag gleiche Woche (Feiertag → Do)
ZahlungsdatumdateDatum des Zahlungseingangs
Rechnungs-PDFattachmentgeneriertes PDF (Server-Upload)
ZahlungsstatussingleSelectOffen / Teilbezahlt / Bezahlt / Überfällig
MahnstatussingleSelectKeine / Erinnerung1 / Erinnerung2 / Mahnung
Hinweis Select-Felder: Airtable erlaubt das Anlegen neuer Select-Optionen nicht per PATCH auf das Feld (schlägt mit INVALID_REQUEST_UNKNOWN fehl). Workaround: Datensatz mit typecast: true anlegen → Option wird automatisch erzeugt → Datensatz wieder löschen.

Neue Tabelle Zahlungseingänge

FeldnameTypZweck
LeadmultipleRecordLinksVerknüpfung zur Leads-Tabelle
RechnungsnummersingleLineTextPflicht für DATEV-Abgleich
BetragnumberTeilbetrag dieser Zahlung
DatumdateEingangsdatum
StatussingleSelectErwartet / Eingegangen / Überfällig

Bereits vorhandene Felder (für Rechnung)

Anrede · Vorname · Nachname · Unternehmen
Straße · PLZ · Ort · Email
Auftragshöhe · Auftragsdatum · Sender · Kundennummer (AutoNumber)
2

Rechnungs-Generator

Ablauf

1. User klickt Button in Airtable (Leads-View)
2. Airtable Automation → POST /rechnung/generieren auf Hetzner
3. Server liest Lead-Felder aus Airtable API
4. Server generiert PDF (reportlab) + ZUGFeRD XML (facturx)
5. Server lädt PDF als Attachment zurück in Airtable-Record
6. Server setzt: Rechnungsnummer, Rechnungsdatum, Zahlungsziel
7. Server sendet PDF per E-Mail an Kunde (BCC: produktion@)

PDF-Template Abgenommen v8

Das Template ist fertiggestellt (rechnung.py, v8). Es muss auf den Server übertragen werden.

Positionslogik

positionen = [("Paketpreis " + sender, auftragshöhe)]  # immer
if erweiterung1 > 0: positionen.append(("Erweiterung 1", erweiterung1))
if erweiterung2 > 0: positionen.append(("Erweiterung 2", erweiterung2))
if verlängerung > 0: positionen.append(("Verlängerung",  verlängerung))
if verlängerung2 > 0: positionen.append(("Verlängerung 2", verlängerung2))

netto  = sum(b for _, b in positionen)
mwst   = round(netto * 0.19, 2)
brutto = round(netto + mwst, 2)

Rechnungsnummer-Format JJMMKWNR

SegmentBedeutungBeispiel
JJJahr 2-stellig26
MMMonat 2-stellig07
KWKalenderwoche 2-stellig28
NRLaufende Nr. pro KW, 2-stellig01

Beispiel: 26072801 = Jahr 2026, Juli, KW 28, erste Rechnung.
Laufende Nummer: Airtable nach Rechnungsnummer LIKE '2628%' filtern, max + 1.

Zahlungsziel

def get_zahlungsziel(rechnungsdatum):
    days_to_friday = (4 - rechnungsdatum.weekday()) % 7
    ziel = rechnungsdatum + timedelta(days=days_to_friday)
    if ziel in holidays.Germany():
        ziel -= timedelta(days=1)  # Donnerstag
    return ziel

ZUGFeRD / Factur-X

Profil EN 16931 (Comfort) — gesetzlicher Standard für DE B2B ab 2025. Das XML wird direkt in das PDF eingebettet, kein separater Anhang.
pip3 install facturx reportlab Pillow holidays requests

Pflichtfelder im XML: Rechnungsnummer, Datum, Zahlungsziel, Verkäufer (vollständig), Käufer, Positionen, Steuern, IBAN.

3

Ratenzahlung

Eine Rechnung pro Auftrag. Teilzahlungen werden in der Tabelle Zahlungseingänge erfasst. Jede Zahlung trägt die Rechnungsnummer (Pflicht für DATEV).

Summe Eingänge = Brutto     → Zahlungsstatus: Bezahlt
0 < Summe < Brutto          → Zahlungsstatus: Teilbezahlt
Summe = 0                   → Zahlungsstatus: Offen

Nach jeder Buchung: Zahlungsstatus im Lead-Record automatisch aktualisieren.

4

Mahnwesen

ZeitpunktAktionMahnstatus
Mo (Rechnungstag)Rechnung versenden
Mo + 7 TageZahlungserinnerungErinnerung1
Mi + 9 Tage2. ErinnerungErinnerung2
Mo + 14 TageFormale MahnungMahnung
Mailtexte ausstehend — werden vom Auftraggeber geliefert (4 Texte: Rechnungsversand + 3 Mahnstufen).
5

DATEV / Addison Export

Kontenrahmen SKR03

KontoZweck
8400Erlöse
1776Umsatzsteuer 19%
1200Bank
DebitorFirmenname (wie auf Rechnung) — kein Nummernschema bis 01/2027

Buchungslogik

Rechnungsstellung:   8400 (Erlöse) an Debitor (Firmenname)
Zahlungseingang:     1200 (Bank)   an Debitor (Firmenname)
Steuerberater Andreas Wirth (03.07.2026): „Rechnungsnummer ist zwingend. Zahlungseingänge werden anhand der Rechnungsnummer zugebucht. Kundennummern (10000+) erst zum Jahreswechsel 01/2027."

Export: monatlicher CSV-Buchungsstapel im DATEV-Format (EXTF, Version 700). Pflichtfelder je Zeile: Rechnungsnummer · Datum · Debitor · Nettobetrag · Konto 8400 · USt-Konto 1776 · Bruttobetrag.

6

Kampagnen-App Spätere Phase

Wird erst gebaut, wenn das Rechnungssystem vollständig läuft. Details in separatem Briefing.

!

Offene Punkte

#WasStatus
1 Mailtexte: Rechnungsversand + 3 Mahnstufen Ausstehend
2 Mailtexte: Kampagnen-App (3 Mails) Ausstehend
3 PDF-Template + Assets auf Hetzner übertragen Build-Start
CC

Hinweise für die Umsetzung mit Claude