Neues Feature: Gap-Report für ZUGFeRD-Mapping (Prüfung auf fehlende Felder)

Neues Feature: Gap-Report für ZUGFeRD-Mapping

Unser KI-gestütztes ZUGFeRD-Mapping hat ein neues Feature bekommen, das die Arbeit noch einfacher macht!

Das Problem

Die KI mappt automatisch ~90% der ZUGFeRD-Felder. Aber was ist mit den fehlenden 10%?
Bisher musste man selbst herausfinden, welche Felder in FileMaker noch fehlen und wie man sie anlegt.

Die Lösung: Gap-Report

Bildschirmfoto 2025-10-10 um 18.37.20.

Ab sofort erstellt die KI einen detaillierten Gap-Report für alle fehlenden Felder:

Was der Gap-Report liefert:

Welches Feld fehlt (z.B. invoiceCurrencyCode)
ZUGFeRD-Code (z.B. BT-5)
Beschreibung (was bedeutet das Feld?)
Pflicht oder Optional? (Priorität HOCH/NIEDRIG)
Konkrete Empfehlung für FileMaker
Beispielwerte zur Orientierung

Beispiel:

❌ invoiceCurrencyCode (BT-5) - PFLICHT
   Beschreibung: Währungscode der Rechnung
   Empfehlung: Textfeld mit Werteliste (EUR, USD, CHF, GBP)
   Beispiel: EUR

❌ unitCode (BT-130) - PFLICHT
   Beschreibung: Einheitencode (UN/ECE)
   Empfehlung: Textfeld mit Werteliste (C62, HUR, MTR, KGM, LTR)
   Beispiel: C62 (Stück), HUR (Stunden)

ℹ️ deliveryTerms (BT-20) - Optional
   Beschreibung: Lieferbedingungen (IncoTerms)
   Empfehlung: Textfeld mit Werteliste (EXW, FOB, CIF, DAP, DDP)
   Beispiel: DAP

Vorteile

Vorher: “15 Felder fehlen” - und jetzt?
Nachher: Konkrete Schritt-für-Schritt-Anleitung, was genau anzulegen ist.

Perfekt für FileMaker-Entwickler ohne ZUGFeRD-Kenntnisse!

Fazit

Das KI-Mapping wird immer intelligenter. Nicht nur automatisch mappen, sondern auch aktiv beim Nacharbeiten helfen.

ZUGFeRD-Compliance wird zum Kinderspiel.


Update: Oktober 2025
Feature: Gap-Report mit konkreten FileMaker-Empfehlungen
Status: Live

#FileMaker #ZUGFeRD #KI #Automatisierung #ERechnung


KI-gestütztes Feld-Mapping in ZUGFeRD Swite , ab morgen Abend verfügbar

Mit ZUGFeRD Swite steht ab sofort ein vollständig automatisiertes, KI-gestütztes Feld-Mapping für FileMaker zur Verfügung. Das System analysiert eigenständig sämtliche FMPXML-Exports aus FileMaker und erstellt innerhalb weniger Sekunden eine komplette Zuordnung zwischen den Quellfeldern und den ZUGFeRD-Zielfeldern. Damit entfällt der aufwendige manuelle Mapping-Prozess, der bislang bei jeder neuen Installation nötig war, Die KI übernimmt die gesamte Arbeit und liefert ein fertiges JSON-Mapping, das sofort in FileMaker übernommen wird. Das ganze erweitert unsere AddOns im Bereich ZUGFeRD. Alle Funktionen bleiben bestehen, das Mapping, mit einem derzeitigen Arbeitsaufwand von ca. 1 Stunde wird auf wenige Minuten reduziert.

Das Problem: Komplexes Field-Mapping überfordert Anwender

Wer schon einmal versucht hat, ZUGFeRD-konforme elektronische Rechnungen aus einem bestehenden ERP- oder Warenwirtschaftssystem zu erzeugen, kennt die Herausforderung: 75+ ZUGFeRD-Felder müssen den vorhandenen Datenfeldern zugeordnet werden. Ein mühsamer, fehleranfälliger Prozess, der für unerfahrene Anwender kaum zu bewältigen ist.

Die klassische Vorgehensweise:

  • Manuelles Durchgehen jedes einzelnen ZUGFeRD-Feldes
  • Suchen des passenden Quellfeldes in verschiedenen Tabellen
  • Copy & Paste von Feldnamen
  • Stundenlange Trial-and-Error-Sessions
  • Häufige Fehler durch Tippfehler oder falsche Zuordnungen

Das Ergebnis: Frustration, Zeitverlust und hohe Fehlerquote.

In unserem Bisherigen AddOn, deshalb das händische Mappen ohne in den FileMaker-Scripten Änderungen vornehmen zu müssen.

Die Lösung: KI macht das Mapping automatisch

Nun aber übernimmt diesen Schritt die KI – Künstlicher Intelligenz (Claude API von Anthropic).

So funktioniert es

Das System besteht aus drei einfachen Schritten:

1. Datenexport aus FileMaker

Der Anwender exportiert 7 XML-Dateien aus seinem System:

  • preferences.xml – Enthält alle ZUGFeRD-Zielfelder (die Referenz)
  • invoice.xml – Rechnungskopfdaten (Rechnungsnummer, Datum, Summen, etc.)
  • buyer.xml – Kundendaten (Name, Adresse, USt-ID, etc.)
  • seller.xml – Verkäuferdaten (Firma, Adresse, Kontakt, etc.)
  • finance.xml – Zahlungsinformationen (IBAN, BIC, Zahlungsbedingungen)
  • payments.xml – Zahlungsdetails und Fälligkeiten
  • items.xml – Rechnungspositionen (Artikel, Mengen, Preise, Steuern)

Diese Dateien werden automatisch nacheinander auf den Server hochgeladen – kein manuelles Handling nötig.

2. KI-gestütztes Mapping

Nach dem Upload wird das KI-Mapping-Script gestartet:

URL: https://ihr-server.de/ki_mapping/start_mapping.php

Was passiert im Hintergrund?

  1. Datenanalyse: Das System liest alle 7 XML-Dateien ein
  2. Feldextraktion: ZUGFeRD-Zielfelder und Quellfelder werden extrahiert
  3. Intelligente Analyse: Die KI analysiert:
    • Feldnamen (semantische Ähnlichkeit)
    • Beispieldaten aus den ersten 3 Datensätzen
    • Datentypen und -strukturen
  4. Automatisches Mapping: Die KI ordnet jedem ZUGFeRD-Feld das passende Quellfeld zu

Dauer: 5-15 Sekunden (abhängig von der Datenmenge)

3. JSON-Response mit fertigem Mapping

Das System gibt eine strukturierte JSON-Antwort zurück:

{
    "success": true,
    "message": "39 von 43 Feldern erfolgreich gemappt",
    "mapping": {
        "buyerName": "buyer.BuyerName",
        "buyerCity": "buyer.BuyerCity",
        "buyerStreet": "buyer.BuyerStreet",
        "invoiceNumber": "invoice.InvoiceNumber",
        "invoiceDate": "invoice.InvoiceIssueDate",
        "totalGrossAmount": "invoice.InvoiceLegalMonetaryTotalTaxInclusiveAmount",
        "payeeIBAN": "finance.payeeIBAN",
        "quantity": "items.LineInvoicedQuantity",
        "priceNet": "items.LineNetPriceAmount",
        ...
    },
    "statistics": {
        "total_zugferd_fields": 43,
        "mapped_fields": 39,
        "unmapped_fields": 4,
        "unmapped_list": ["deliveryTerms", "lieferschein_nr", ...]
    }
}

Diese JSON kann direkt in FileMaker (oder jedem anderen System) weiterverarbeitet werden.

Technische Details

Architektur

Das System besteht aus drei PHP-Scripten:

1. receive_xml.php – XML-Upload-Handler

  • Empfängt die 7 XML-Dateien nacheinander
  • Automatische Reihenfolgen-Erkennung (kein manuelles Benennen nötig)
  • Parst FileMaker FMPXMLRESULT Format
  • Extrahiert Feldnamen und Beispieldaten
  • Speichert XML + JSON-Metadaten

2. process_mapping.php – KI-Mapping-Engine

  • Liest alle 7 XML-Dateien
  • Extrahiert ZUGFeRD-Zielfelder aus preferences.xml
  • Sammelt Quellfelder + Beispieldaten aus den anderen 6 Dateien
  • Erstellt intelligenten Prompt für Claude API
  • Parst KI-Response und validiert Mapping
  • Speichert Ergebnis als JSON mit Timestamp

3. start_mapping.php – FileMaker-Interface

  • Einfacher Endpoint für FileMaker “Aus URL Einfügen”
  • Startet Mapping-Engine
  • Gibt JSON-Response direkt zurück
  • Timeout: 60 Sekunden (ausreichend für alle Fälle)

Keine Dependencies nötig!

Das System nutzt PHP-Bordmittel:

  • SimpleXML für XML-Parsing
  • cURL für API-Kommunikation
  • Keine externen Libraries erforderlich

Der bestehende vendor/-Ordner auf dem Server bleibt unangetastet.

KI-Integration: Claude API

Wir nutzen Claude 3 Haiku von Anthropic:

  • Schnell (5-15 Sekunden Response)
  • Günstig (ca. 0,01-0,05 EUR pro Mapping)
  • Hohe Qualität bei semantischer Analyse
  • Versteht natürliche Sprache UND Datenstrukturen

Die KI erhält:

  • Liste aller ZUGFeRD-Zielfelder
  • Alle Quellfelder mit Beispieldaten
  • Mapping-Regeln (Präzision, Format, etc.)

Und gibt zurück:

  • Vollständiges Mapping als JSON
  • Confidence-Level implizit durch Match-Quality
  • null für nicht zuordenbare Felder

Vorteile des Systems

✅ Für Anwender

  • Keine technischen Kenntnisse erforderlich
  • 90%+ automatische Trefferquote
  • Sekunden statt Stunden
  • Fehlerrate nahezu Null
  • Wiederverwendbare Mappings

✅ Für Entwickler/Administratoren

  • Einfache Installation (3 PHP-Dateien)
  • Keine komplexen Dependencies
  • Vollständig protokolliert (Logs in csv_uploads/)
  • Versionierte Mappings (Timestamp-basiert)
  • Anpassbare Mapping-Regeln (Prompt kann erweitert werden)

✅ Für Unternehmen

  • Drastische Zeitersparnis bei der Implementierung
  • Reduzierte Fehlerkosten
  • Schnellere Onboarding-Prozesse
  • Skalierbar (beliebig viele Mandanten/Systeme)
  • Kosteneffizient (< 5 Cent pro Mapping)

Integration in FileMaker

Script-Aufbau

# Schritt 1-7: XML-Uploads
Aus URL einfügen [
  URL: "https://server.de/ki_mapping/receive_xml.php"
  Daten: $xml_preferences
  Methode: POST
]

# ... weitere 6 Uploads ...

# Schritt 8: KI-Mapping starten
Aus URL einfügen [
  URL: "https://server.de/ki_mapping/start_mapping.php"
  In Variable: $$MappingResponse
  Timeout: 30 Sekunden
]

# Schritt 9: JSON parsen und verwenden
Feld setzen [ feldmapping::json ; $$MappingResponse ]

JSON-Weiterverarbeitung

Das Mapping kann direkt genutzt werden:

  • Import in FileMaker-Tabellen
  • Verwendung für ZUGFeRD-Export
  • Speicherung als wiederverwendbares Template
  • Export für andere Systeme

Fazit

Was früher Stunden manueller Arbeit erforderte, erledigt die KI nun in Sekunden – mit höherer Qualität und weniger Fehlern.

Das System zeigt eindrucksvoll, wie KI komplexe, repetitive Aufgaben übernehmen kann, ohne dass Anwender technisches Spezialwissen benötigen.

ZUGFeRD-Integration war noch nie so einfach.


Technische Anforderungen

  • PHP 7.4+ (SimpleXML, cURL)
  • Anthropic API Account (ab 5 EUR/Monat ausreichend)
  • FileMaker Pro/Server

Unser ZUGFeRD AddOn erhält ein Update

Im Zuge der Zusammenarbeit mit dem geschätzten Entwickler Alexander Lemuth haben wir in den letzten 2 Wochen etliche spannende Änderungen und Verbesserungen vorgenommen. Ursprünglich war geplant, die Implementierung gemeinsam per Zoom durchzuführen. Doch wie es oft bei guter Zusammenarbeit der Fall ist: während der intensiven Auseinandersetzung mit der bestehenden Lösung sind uns immer mehr interessante Details und Optimierungsmöglichkeiten aufgefallen. Was als einfaches Update beginnen sollte, entwickelte sich zu einer grundlegenden Überarbeitung. Die kritischen Fragen von Alexander und seine praktischen Anforderungen haben uns dazu gebracht, tiefer zu graben und das FM ZUGFeRD AddOn kräftig zu überarbeiten. Das Ergebnis ist Version 2.0, eine deutlich flexiblere, intuitivere und mächtigere Lösung, die wir ohne diesen produktiven Austausch nie erreicht hätten. Ein herzliches Dankeschön an dieser Stelle an Alexander für die konstruktiven Impulse, die geduldigen Tests und das ehrliche Feedback!

FM ZUGFeRD 2.0 – Die Evolution der elektronischen Rechnungsstellung in FileMaker

Die elektronische Rechnungsstellung wird in Deutschland und Europa zunehmend zur Pflicht. Mit FM ZUGFeRD 2.0 präsentieren wir die nächste Generation unseres AddOns für FileMaker – komplett überarbeitet, intuitiver und flexibler als je zuvor.

Was ist neu? Die wichtigsten Features im Überblick

🎯 1. Flexible Primärschlüssel-Zuordnung

Bildschirmfoto 2025-09-29 um 18.25.42.

Endlich: Abweichende Primärschlüssel für maximale Flexibilität! Nicht jede FileMaker-Lösung nutzt standardisierte Primärschlüssel. Mit der neuen Funktion können Sie für jeden Bereich (Seller, Buyer, Invoice, Items) einen alternativen Primärschlüssel definieren.

Was bedeutet das für Sie?

  • Keine Anpassung Ihrer bestehenden Datenstruktur nötig
  • Volle Kontrolle über die Datenzuordnung
  • Nahtlose Integration in Ihre vorhandene FileMaker-Lösung

So funktioniert’s: Ein einfacher Dialog ermöglicht die Auswahl eines abweichenden Identifikationsfeldes. Das System nutzt dann automatisch diesen alternativen Schlüssel für die Datenzuordnung – perfekt für komplexe Datenmodelle mit individuellen Beziehungsstrukturen.

🖨️ 2. Erweiterte Drucklayout-Verwaltung

Bildschirmfoto 2025-09-29 um 18.26.50.

Die neue Drucklayout-Funktion bietet Ihnen volle Kontrolle über die Ausgabe Ihrer ZUGFeRD-Dokumente:

Zwei Ansichtsmodi:

  • Formularansicht: Für detaillierte Einzelrechnungen mit allen Informationen
  • Tabellenansicht: Für kompakte Listenansichten und Sammelrechnungen

Intelligente Layout-Zuordnung:

  • Separate Layouts für verschiedene Ausgabeformate
  • Flexible Feldzuordnung pro Ansicht
  • Automatische Anpassung an Ihre Corporate Identity

Das bedeutet: Einmal konfigurieren, mehrfach nutzen – ohne ständige manuelle Anpassungen.

🎨 3. Überarbeitete Benutzeroberfläche

Die komplette Oberfläche wurde von Grund auf neu gestaltet. Moderne, intuitive Navigation durch alle Konfigurationsbereiche:

9 übersichtliche Tabs:

  1. Info – Zentrale URL-Konfiguration für alle Endpunkte
  2. Payments – Rechnungskopf und allgemeine Daten
  3. Buyer – Käufer-/Kundendaten mit vollständiger Adressverwaltung
  4. Seller – Verkäufer-/Firmendaten inkl. Steuer-IDs
  5. Finance – Bankinformationen und Zahlungskonditionen
  6. Invoice – Rechnungsbeträge, Steuern und Totalsummen
  7. Items – Rechnungspositionen mit detaillierten Artikeldaten
  8. Print – Drucklayout-Verwaltung für beide Ansichtsmodi
  9. Testen – Integrierte Demo- und Validierungsfunktionen

Das neue Design punktet mit:

  • Klarer visueller Hierarchie
  • Zweisprachigen Labels (Deutsch/English)
  • Kontextsensitiven Hilfetexten
  • Farblich gekennzeichneten Bereichen für schnellere Orientierung

🔄 4. Intelligentes Feld-Mapping

Das Herzstück von FM ZUGFeRD: Die automatisierte Feldzuordnung.

Wie es funktioniert:

  1. Layout wählen: Dropdown-Auswahl Ihrer FileMaker-Tabellen
  2. Felder zuordnen: Drag & Drop Ihrer FileMaker-Felder zu ZUGFeRD-Standardfeldern
  3. Validieren: Automatische Prüfung auf Vollständigkeit und Konformität
  4. Testen: Sofortige Vorschau der generierten Dokumente

Unterstützte Datenquellen:

  • Beliebige FileMaker-Tabellen
  • Portal-Beziehungen für Positionsdaten
  • Berechnungsfelder für dynamische Werte
  • Globale Felder für Standardwerte

📋 5. EN 16931 Konformität garantiert

Alle generierten ZUGFeRD-Dokumente entsprechen der Europäischen Norm EN 16931 für elektronische Rechnungen.

Technische Details:

  • Format: PDF/A-3 mit eingebettetem XML
  • Profile: BASIC, COMFORT, EXTENDED
  • Standard: ZUGFeRD 2.x / Factur-X
  • Kompatibilität: UBL (Universal Business Language)

Validierung in Echtzeit: Das AddOn prüft kontinuierlich:

  • Pflichtfelder gemäß gewähltem Profil
  • Korrekte Datenformate (Datum, Währung, Steuersätze)
  • Konsistenz zwischen Positionen und Gesamtsummen
  • Gültige ISO-Codes für Länder, Währungen und Einheiten

🧪 6. Integrierte Test- und Demo-Funktionen

Der neue Testen-Tab ist Ihr Playground für ZUGFeRD-Dokumente:

Demo-Funktionen:

  • Create ZUGFeRD Demo: Erstellt Beispielrechnungen zum Testen
  • Create UBL Demo: Generiert UBL-Testdokumente
  • Read ZUGFeRD Demo: Liest und analysiert vorhandene ZUGFeRD-Dateien
  • Read UBL Demo: Importiert UBL-Dokumente zur Validierung

Export/Import von Konfigurationen:

  • Einstellungen exportieren für Backup oder Migration
  • Konfigurationen importieren zwischen Test- und Produktivumgebungen
  • Versionierung Ihrer Mapping-Definitionen

Live-Vorschau: Zwei Container zeigen in Echtzeit:

  • XML-Container: Die generierte ZUGFeRD-XML-Struktur
  • PDF-Container: Das finale PDF/A-3-Dokument mit eingebettetem XML

🌐 7. Nahtlose HTTP-Integration

FM ZUGFeRD arbeitet mit PHP-Scripten (local oder Server) über standardisierte HTTP-Schnittstellen:

Der Workflow:

  1. FileMaker sendet Rechnungsdaten via POST an konfigurierten Endpoint
  2. PHP-Service generiert ZUGFeRD-konforme Struktur
  3. XML wird nach EN 16931 erstellt und validiert
  4. PDF/A-3 wird mit eingebettetem XML erzeugt
  5. Fertiges Dokument wird zum Download bereitgestellt
  6. FileMaker lädt automatisch herunter und speichert in Container-Feld

Ihre Vorteile:

  • Keine lokale PDF-Bibliothek erforderlich
  • Zentrale Verwaltung der Generierungslogik
  • Skalierbar für hohe Dokumentenvolumen
  • Einfache Updates der ZUGFeRD-Spezifikationen

📊 8. Präzise Steuerberechnung

Die Steuerberechnung erfolgt auf zwei Ebenen – vollständig automatisiert:

Positionsebene: Jede Rechnungsposition enthält:

  • Einzelpreis (netto)
  • Menge und Einheit
  • Steuersatz (%)
  • Steuerkategorie (S, Z, E, AE, …)
  • Automatische Berechnung des Zeilentotals

Dokumentebene: Automatische Aggregation zu:

  • Gesamtnettobetrag (Summe aller Positionen)
  • Steuerblöcke pro Steuersatz
  • Steuerbemessungsgrundlage pro Satz
  • Gesamtsteuerbetrag
  • Bruttoendbetrag

Wichtig: Das System stellt sicher, dass Position- und Dokumentsummen immer konsistent sind!

Praktische Anwendungsfälle

Szenario 1: Standardrechnung mit 19% MwSt.

Artikel: "Beratungsdienstleistung"
Menge: 8 Stunden
Einzelpreis: 120,00 EUR (netto)
Steuersatz: 19%

→ Netto: 960,00 EUR
→ MwSt.: 182,40 EUR
→ Brutto: 1.142,40 EUR

FM ZUGFeRD erstellt automatisch ein PDF/A-3 mit eingebettetem XML – bereit für die elektronische Übermittlung.

Szenario 2: Rechnung mit mehreren Steuersätzen

Position 1: Bücher (7% MwSt.) → 100,00 EUR netto
Position 2: Software (19% MwSt.) → 500,00 EUR netto

→ Steuerblock 7%: Basis 100,00 EUR, Steuer 7,00 EUR
→ Steuerblock 19%: Basis 500,00 EUR, Steuer 95,00 EUR
→ Gesamt: 702,00 EUR brutto

Das AddOn erstellt automatisch separate Steuerblöcke für jeden Satz – EN 16931 konform.

Szenario 3: Grenzüberschreitende Rechnung (Reverse Charge)

Verkäufer: Deutschland (DE)
Käufer: Österreich (AT) mit gültiger UID
Steuerkategorie: AE (Reverse Charge)

→ Nettobetrag: 2.500,00 EUR
→ Steuersatz: 0% (Hinweis auf Reverse Charge)
→ Bruttobetrag: 2.500,00 EUR

Perfekt für B2B-Geschäfte innerhalb der EU.

Best Practices für Ihre FileMaker-Lösung

1. Datenstruktur vorbereiten

Empfohlene Felder in Ihrer Rechnungstabelle:

  • rg_nummer (Text): Eindeutige Rechnungsnummer
  • rg_datum (Datum): Rechnungsdatum im Format YYYY-MM-DD
  • rg_faellig (Datum): Fälligkeitsdatum
  • rg_waehrung (Text): ISO-Währungscode (EUR, USD, CHF, …)
  • rg_kunde_id (Zahl): Fremdschlüssel zur Kundentabelle
  • rg_netto (Zahl): Nettosumme (berechnet)
  • rg_steuer (Zahl): Steuerbetrag (berechnet)
  • rg_brutto (Zahl): Bruttosumme (berechnet)

2. Berechnungsfelder nutzen

Steuerbetrag berechnen:

Round ( rg_netto * 0.19 ; 2 )

Bruttobetrag berechnen:

rg_netto + rg_steuer

Aggregation von Positionen:

Sum ( rg_positionen::pos_netto )

3. Validierung implementieren

Prüfen vor Export:

  • Sind alle Pflichtfelder gefüllt?
  • Ist die USt-ID formal korrekt?
  • Stimmen Positions- und Kopfsummen überein?
  • Sind ISO-Codes korrekt (Land, Währung, Einheit)?

FileMaker-Skript Beispiel:

If [ IsEmpty ( rg_nummer ) or IsEmpty ( rg_datum ) ]
    Show Custom Dialog [ "Fehler"; "Pflichtfelder fehlen!" ]
    Exit Script [ Text Result: False ]
End If

# ZUGFeRD Export starten
Perform Script [ "ZUGFeRD - Export Rechnung" ]

4. Layouts strukturieren

Empfohlene Layout-Struktur:

  • Formularansicht: Vollständige Rechnung mit Header, Positionen, Footer
  • Listenansicht: Kompakte Positionsübersicht
  • Druckansicht: Formatiert für PDF-Export mit Corporate Design

5. Fehlerbehandlung einbauen

Typische Fehlerquellen:

  • Leere Pflichtfelder
  • Ungültige Datumsformate
  • Falsche Währungscodes
  • Fehlende Beziehungen zu Stammdaten

Lösung: Validierungs-Skripte vor dem Export ausführen!

Technische Details für Entwickler

Unterstützte Einheitencodes (UN/ECE Recommendation 20)

Die wichtigsten Codes für den deutschen Markt:

Code Bedeutung Verwendung
C62 Stück Einzelne Artikel, Produkte
HUR Stunde Dienstleistungen, Beratung
DAY Tag Tagessätze, Miete
MTR Meter Längenangaben, Textilien
MTK Quadratmeter Flächen, Immobilien
MTQ Kubikmeter Volumen, Baustoffe
KGM Kilogramm Gewichtsangaben
TNE Tonne Schwergewicht, Rohstoffe
LTR Liter Flüssigkeiten
SET Set Produktsets, Bundles
MON Monat Abonnements, Mieten

Steuerkategorien nach EN 16931

Code Bedeutung Anwendung
S Standard rate Regelsteuersatz (19% in DE)
AA Lower rate Ermäßigter Satz (7% in DE)
Z Zero rated 0% (z.B. innergemeinschaftlich)
E Exempt Steuerbefreit (z.B. Kleinunternehmer)
AE Reverse charge Umkehr der Steuerschuldnerschaft
K Intra-Community Innergemeinschaftliche Lieferung
G Free export Export außerhalb EU
O Outside scope Nicht steuerbar

Rechnungstyp-Codes (UNTDID 1001)

Code Typ Verwendung
380 Commercial Invoice Standardrechnung
381 Credit Note Gutschrift/Stornorechnung
384 Corrected Invoice Korrekturrechnung
389 Self-billed Invoice Gutschriftverfahren
751 Invoice Information Rechnungsinformation

Zahlungsarten (ISO 20022)

Code Zahlungsart
58 SEPA-Überweisung
30 Banküberweisung
48 Kreditkarte
49 Lastschrift
97 Verrechnungsscheck

Lizenzierung und Support

COMFORT-Version

FM ZUGFeRD ist als COMFORT-Version lizenziert und bietet:

  • Vollständige EN 16931 Konformität
  • Alle ZUGFeRD 2.x Profile (BASIC, COMFORT, EXTENDED)
  • UBL-Unterstützung
  • Unbegrenzte Dokumentenerstellung
  • Professioneller Support

Updates und Wartung

  • Regelmäßige Updates bei Änderungen der ZUGFeRD-Spezifikation
  • Anpassungen bei gesetzlichen Änderungen
  • Bug-Fixes und Optimierungen
  • Neue Features basierend auf Kundenanforderungen

Support-Kanäle

  • E-Mail Support: support@filemaker-experts.de
  • Dokumentation: Wiki mit ausführlichen Anleitungen
  • Video-Tutorials: Schritt-für-Schritt Konfiguration
  • Community-Forum: Austausch mit anderen Nutzern

Migration von älteren Versionen

Von FM ZUGFeRD 1.x auf 2.0

Die Migration ist einfach:

  1. Backup erstellen: Sichern Sie Ihre aktuelle Konfiguration
  2. Export Settings: Exportieren Sie Ihre Feldzuordnungen
  3. Update installieren: Neue AddOn-Version in FileMaker laden
  4. Import Settings: Importieren Sie Ihre gespeicherte Konfiguration
  5. Test durchführen: Erstellen Sie Test-Dokumente zur Validierung

Was bleibt erhalten:

  • Alle Feldzuordnungen
  • URL-Konfigurationen
  • Layout-Einstellungen

Was ist neu zu konfigurieren:

  • Drucklayout-Zuordnungen (neue Funktion)
  • Alternative Primärschlüssel (falls gewünscht)

Roadmap: Was kommt als Nächstes?

Wir arbeiten bereits an weiteren Verbesserungen:

Geplante Features (Q2-Q4 2025)

  • 🔄 Batch-Verarbeitung: Mehrere Rechnungen auf einmal exportieren
  • 📧 E-Mail-Integration: Direktversand via FM MailBridge AddOn
  • 🗄️ Archivierung: Automatisches Ablegen in revisionssicheren Archiven
  • 📱 Mobile Optimierung: Rechnungserstellung auf iPad
  • 🤖 KI-Unterstützung: Automatische Felderkennung beim Import
  • 🌍 Weitere Formate: X-Rechnung, Peppol BIS
  • 📊 Analytics: Reporting und Statistiken über ZUGFeRD-Nutzung

Fazit: Bereit für die E-Rechnungs-Pflicht

Mit FM ZUGFeRD 2.0 sind Sie bestens gerüstet für die elektronische Rechnungsstellung:

Rechtskonform: EN 16931 zertifiziert
Flexibel: Passt sich Ihrer FileMaker-Lösung an
Intuitiv: Moderne, übersichtliche Benutzeroberfläche
Zuverlässig: Validierung in Echtzeit
Zukunftssicher: Regelmäßige Updates und Erweiterungen

Ab sofort verfügbar!

Jetzt informieren:


Hinweis: Ab 2025 wird die E-Rechnung in Deutschland für B2B-Transaktionen schrittweise verpflichtend. Mit FM ZUGFeRD erfüllen Sie alle gesetzlichen Anforderungen – heute schon für morgen bereit.

#FileMaker #ZUGFeRD #ERechnung #DigitaleTransformation #Automatisierung


ZUGFeRD mit eigenem PDF-Layout, endlich pragmatisch gelöst

ZUGFeRD FileMaker PDF.

Monate lang stand ich vor dem gleichen Problem: Die PHP-Bibliothek horstoeko/zugferd erzeugt zuverlässig die ZUGFeRD-XML, möchte aber idealerweise, dass man das sichtbare PDF mit FPDF neu aufbaut. Für standardisierte Rechnungen ist das akzeptabel; für gewachsene Corporate-Designs mit sauber gesetzten Typografien, Logos, farbigen Flächen und komplexeren Kopf-/Fußbereichen ist es schlicht unpraktikabel. Mein Ziel war daher, ein beliebiges, bereits perfektes Template-PDF (aus FileMaker, InDesign, Word oder einem anderen System) weiterzuverwenden und ausschließlich die ZUGFeRD-XML sauber zu integrieren – ohne das Layout neu zu programmieren.

Ausgangsproblem – warum der reine FPDF-Weg nicht reicht

Sobald es um reale Layouts geht, wird der FPDF-Weg schnell mühsam: Spaltenbreiten, Zeilenabstände, Schriften, Positionierungen, Logos, CI-Farben – alles muss mühsam nachgebaut werden, obwohl das Layout als fertige PDF längst existiert. Hinzu kommt, dass einzelne PDFs wegen Kompressionsarten, PDF-Versionen oder Producer-Spezifika von FPDI nicht immer direkt importierbar sind. Das kostet Zeit, Nerven und bringt keinen fachlichen Mehrwert, wenn das Ziel schlicht „bestehendes Layout beibehalten, ZUGFeRD einbetten“ heißt.

Die Lösung – Template-PDF nutzen, ZUGFeRD einbetten, robustes Fallback

Ich habe ein Template-System mit mehrstufigem Fallback gebaut, das vorhandene PDFs bevorzugt, FPDI nur nutzt, wenn es geht, andernfalls automatisiert konvertiert oder, falls nötig, das Template schlicht als Basis kopiert und anschließend die ZUGFeRD-XML einbettet. Die ZUGFeRD-Erzeugung bleibt sauber im ZugferdDocumentBuilder, das Einbetten erfolgt mit ZugferdDocumentPdfBuilder::fromPdfFile(…). Ergebnis: Das Layout bleibt 1:1 erhalten, und die PDF wird ZUGFeRD-konform.

Kernpunkte des Ansatzes: • Automatische Template-Erkennung im templates/-Ordner, optional mit layout_config.json für kleinere Koordinaten-/Schrift-Tweaks (falls man doch etwas übersteuern möchte). • Mehrstufiger FPDI-Fallback: Direktimport → Konvertierung (Ghostscript) → sichere Kopie. • Robustes Error-Handling & Logging: Jede Stufe wird sauber protokolliert, inklusive Dateigrößen, Rückgaben und etwaigen Ausnahmen. • Saubere Trennung der Verantwortlichkeiten: Der Builder erzeugt die XML; der PDF-Builder fügt sie einem bestehenden PDF hinzu; FPDF kommt nur noch dann zum Einsatz, wenn wirklich ein Basispapier benötigt wird.

Technischer Ablauf – von Template bis ZUGFeRD-PDF 1. Template laden oder Standard-PDF erzeugen (Upload aus FileMaker per aus URL einfügen) Im Projektverzeichnis liegt ein templates/-Ordner. Dort wird automatisch die erste passende PDF als Template ausgewählt. Deshalb wird die Rechnung immer als template.pdf hochgeladen. Möglich ist auch dort schon die Rechnugs-PDF mit eigenem Datei-Namen zu versehen. Dies ist aber nicht notwendig. Ist FPDI verfügbar und kann das Template öffnen, wird die Seite importiert. Schlägt dies wegen Kompressionsdetails fehl, versucht das System eine Konvertierung (via Ghostscript) und importiert erneut. Misslingt auch das, wird das Template als Datei kopiert und danach direkt mit XML versehen. Nur wenn überhaupt kein Template vorhanden/geeignet ist, wird minimal mit FPDF eine neutrale Seite gebaut. 2. ZUGFeRD-XML generieren Die fachlichen Rechnungsdaten kommen wie gehabt per POST (Rechnungsnummer, Datum, Positionen, Summen, Steuerblöcke, Zahlungsbedingungen etc.). Daraus wird mit ZugferdDocumentBuilder die EN16931-konforme XML erzeugt. 3. XML in PDF integrieren Mit ZugferdDocumentPdfBuilder::fromPdfFile($document, $tempPdfPath) wird die XML in das vorbereitete PDF geschrieben und als finale ZUGFeRD-PDF gespeichert.

Ausschnitt: Template-Erkennung mit mehrstufigem Fallback

Im folgenden Ausschnitt ist das Prinzip komprimiert dargestellt. Beachten: Kommentare sind bewusst ausführlich, da sie beim späteren Debuggen Gold wert sind.

// Template-PDF automatisch erkennen
$templatesDir = __DIR__ . '/templates/';
$templatePdfs = glob($templatesDir . '*.pdf');

if (!empty($templatePdfs)) {
    $templatePdf = $templatePdfs[0];

    try {
        // Versuch 1: FPDI nutzen (falls verfügbar)
        if (!class_exists('Fpdi')) {
            throw new Exception('FPDI-Klasse nicht verfügbar');
        }

        $pdf = new Fpdi();
        $pageCount = $pdf->setSourceFile($templatePdf);
        $tpl = $pdf->importPage(1);
        $pdf->AddPage();
        $pdf->useTemplate($tpl, 0, 0);

        // Als temporäre Basis speichern
        $pdf->Output('F', $tempPdfPath);
        // -> ab hier geht es direkt zum Einbetten der XML

    } catch (Exception $e) {
        // Versuch 2: PDF kompatibel machen und erneut probieren
        $converted = $templatesDir . 'converted_template.pdf';
        if (convertPdfForFpdi($templatePdf, $converted)) {
            try {
                $pdf = new Fpdi();
                $pageCount = $pdf->setSourceFile($converted);
                $tpl = $pdf->importPage(1);
                $pdf->AddPage();
                $pdf->useTemplate($tpl, 0, 0);
                $pdf->Output('F', $tempPdfPath);
                @unlink($converted);
            } catch (Exception $e2) {
                @unlink($converted);
                // Versuch 3: Direkte Kopie als Fallback
                copy($templatePdf, $tempPdfPath);
            }
        } else {
            // Falls Konvertierung nicht möglich: Direkte Kopie
            copy($templatePdf, $tempPdfPath);
        }
    }
} else {
    // Kein Template gefunden -> neutrale FPDF-Seite als Minimalbasis
    $pdf = new FPDF();
    $pdf->AddPage();
    // Optional: Logo/Absender, wenn gewünscht; ansonsten blank lassen
    // $pdf->Image('logo.png', 20, 10, 30, 15);
    $pdf->Output('F', $tempPdfPath);
}

Konvertierung für FPDI-Kompatibilität

Manche PDFs scheitern an der Importhürde wegen Kompressionsart oder PDF-Version. Ich reiche deshalb (falls vorhanden) eine Ghostscript-Konvertierung vor. Der Code ist so geschrieben, dass er ohne Ghostscript nicht abstürzt, sondern sauber weiter macht.

function convertPdfForFpdi($inputPdf, $outputPdf) {
    try {
        // Versuch: Ghostscript (falls exec() und gs vorhanden)
        if (function_exists('exec')) {
            $cmd = 'gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 '
                 . '-dPDFSETTINGS=/prepress -dNOPAUSE -dQUIET -dBATCH '
                 . '-sOutputFile="' . $outputPdf . '" "' . $inputPdf . '" 2>&1';
            $out = [];
            $ret = 0;
            exec($cmd, $out, $ret);
            if ($ret === 0 && file_exists($outputPdf)) {
                return true;
            }
        }
        // Fallback: Wenn kompatibel, reicht Kopie
        return copy($inputPdf, $outputPdf);
    } catch (Exception $e) {
        return false;
    }
}

XML erzeugen und in bestehendes PDF einbetten

Der entscheidende Schritt: Wir nutzen die Stärke der Bibliothek – die XML-Erzeugung – und vermeiden, das Layout neu bauen zu müssen. Dazu erstellen wir den ZugferdDocumentBuilder, setzen alle Pflicht- und optionalen Felder (Dokumenttyp, Beträge, Steuern, Zahlungsbedingungen etc.) und übergeben dieses Dokument anschließend an den PDF-Builder.

// 1) ZUGFeRD-XML vorbereiten
$document = ZugferdDocumentBuilder::createNew(ZugferdProfiles::PROFILE_EN16931);
$document->setDocumentInformation($invoiceNumber, $invoiceTypeCode, new DateTime($invoiceDate), $currency);

// Summation/Steuerblöcke etc. setzen ...
// $document->setDocumentSummation(...);
// $document->addDocumentTax(...);
// $document->addDocumentPaymentMeanToCreditTransfer(...);

// 2) XML in das vorhandene (Template-)PDF einbetten
$pdfBuilder = ZugferdDocumentPdfBuilder::fromPdfFile($document, $tempPdfPath);
$pdfBuilder->generateDocument();
$pdfBuilder->saveDocument($outputPath);

Template-Konfiguration: optional, klein, hilfreich

Damit ich bei Bedarf Kleinigkeiten ohne neues Template anfassen kann, lese ich eine layout_config.json ein. Sie enthält vor allem Koordinaten und Schriftgrößen für Textbausteine, die ich optional über FPDF ergänze (z. B. Adressblock, Infospalte, Summenfeld) – praktisch, falls Kundenvarianten leichte Unterschiede verlangen, aber kein komplett eigenes Template rechtfertigen.

Beispielhafte Keys (gekürzt): page_width, margin_left, sender_start_x, right_column_label_x, document_type_y, table_start_y, default_font, header_bg_color, summary_label_x, template_pdf. Fehlt die Datei, läuft das System mit vernünftigen Standardwerten weiter – der ZUGFeRD-Teil ist davon ohnehin unabhängig.

Logging und Fehlertoleranz

Alle wesentlichen Schritte werden in uploads/zugferd_log.txt mit Zeitstempel geloggt: Welche Stufe gegriffen hat, Dateigrößen vor/nach Verarbeitung, gefundene Templates, etwaige Exceptions inklusive Trace. Damit sind Fehlersuche und spätere Betriebsbeobachtung unaufwendig. Auch wenn FPDI oder Ghostscript nicht verfügbar sind, bleibt das System funktionsfähig, da es am Ende immer auf die „Kopie + Einbettung“-Strategie zurückfällt.

Was bleibt von FPDF?

FPDF bleibt im Projekt lediglich als Minimal-Fallback oder für sehr kleine Ergänzungen (z. B. dynamischer Hinweistext) erhalten. Logos, Balken, CI-Elemente usw. kommen aus dem Template, so wie es sein soll. Fazit

Statt aufwendig ein bestehendes Corporate-Design in FPDF nachzubauen, nutze ich jetzt vorhandene PDFs die in FileMaker erzeugt werden unverändert und lasse lediglich die ZUGFeRD-XML sauber einbetten. Die Kombination aus Template-Erkennung, FPDI-Fallback, optionaler Konvertierung und konsequentem Error-Handling führt zu einem robusten, praxistauglichen Workflow: Template bzw. die aktuelle Rechnung hochladen, Daten senden, fertige ZUGFeRD-PDF erhalten. Wenn Sie bereits ein gutes Rechnungslayout in FileMaker haben und nur „ZUGFeRD dazu“ brauchen, ist dieser Ansatz die pragmatische Abkürzung.


Neu: ZUGFeRD/UBL Reader Add-on für FileMaker

Elektronische Rechnungen sind längst Standard, insbesondere im öffentlichen Bereich mit UBL/XRechnung und bei Geschäftspartnern mit ZUGFeRD 2.1.1. Für viele FileMaker-Anwender stellt sich die Frage: Wie lassen sich diese Rechnungen direkt in bestehende Systeme integrieren, ohne jede Datei manuell zu erfassen?

Zugferd Reader.

Genau hier setzt unser neues ZUGFeRD/UBL Reader Add-on an.

Was kann das Add-on? • ZUGFeRD-PDFs einlesen: XML wird automatisch erkannt und verarbeitet • UBL/XRechnung unterstützen: kompatibel mit den gängigen Behörden- und Portallösungen • Strukturierte JSON-Ausgabe: Kopf-, Positions- und Steuerdaten stehen FileMaker-konform bereit • Beispielskripte und Mapping: sofort loslegen mit vorbereiteten Routinen • Flexibel im Einsatz: Einzelplatz oder Serverumgebung

Warum ist das wichtig? • Zeitersparnis: keine manuelle Eingabe von Rechnungsdaten mehr • Rechtssicherheit: Unterstützung aktueller Standards für E-Rechnung • Offen & erweiterbar: klare Dokumentation, kein Vendor-Lock-in • Praxisnah: entwickelt von FileMaker-Experten mit jahrzehntelanger Projekterfahrung

Für wen ist das interessant? • Unternehmen mit Pflicht zur E-Rechnung (öffentlicher Sektor, Lieferanten) • FileMaker-Entwickler, die Buchhaltung oder ERP-Funktionen integrieren möchten • Teams, die Eingangsrechnungen automatisiert verarbeiten wollen


ZUGFeRD nicht nur erstellen, sondern auch lesen

Zugferd lesen.

Die meisten Entwickler verbinden ZUGFeRD oder Factur-X mit dem klassischen Anwendungsfall:

Eine Rechnung in FileMaker erzeugen, die dann als PDF mit eingebettetem XML an den Kunden geht. Doch im täglichen Einsatz ergibt sich oft das umgekehrte Szenario: Eingehende ZUGFeRD-Rechnungen sollen in das eigene System importiert und weiterverarbeitet werden. Genau hier zeigt sich die eigentliche Stärke des Standards, denn er erlaubt eine strukturiert maschinenlesbare Übergabe von Rechnungsdaten ohne dass man auf PDF-Parsing oder OCR-Erkennung angewiesen wäre.

Der Ansatz:

Mein Ziel war es, neben der Erzeugung auch das Einlesen von ZUGFeRD-Dateien in eine FileMaker-Lösung zu integrieren. Der Workflow ist dabei erstaunlich klar: 1. Der Anwender zieht eine ZUGFeRD-PDF in ein Containerfeld. 2. Ein FileMaker-Script übernimmt den Upload und prüft die Datei. 3. Die eingebettete XML-Datei wird mit Hilfe des PHP-Pakets horstoeko/zugferd extrahiert und ausgewertet. 4. Als Rückgabe erhalte ich ein kompaktes JSON, das sich in FileMaker direkt weiterverarbeiten lässt.

Damit ist der Kreis geschlossen: Eingehende Rechnungen können automatisch gelesen, geprüft und in die eigene Datenbank übernommen werden.

Technische Umsetzung

Im einfachsten Fall genügt ein FileMaker-Skript, das den Containerinhalt temporär exportiert und per curl an das Server-Skript übergibt:

Variable setzen [ $filename ; HoleContainerAttribute ( Rechnung::g_pdf ; "filename" ) ]
Variable setzen [ $tmpFS ; Hole ( TemporärerPfad ) & $filename ]
Exportiere Feldinhalt [ Rechnung::g_pdf ; "file:" & $tmpFS ]
Variable setzen [ $url ; "[meine-domain.de/mc/receiv...](https://meine-domain.de/mc/receive_pdf_upload.php)" ]
Variable setzen [ $curl ; "--request POST --upload-file " & Quote ( $tmpFS ) & 
                          " --header \"Content-Type: application/pdf\"" ]
Aus URL einfügen [ Auswahl ; Mit Dialog: Aus ; Ziel: $$response ; $url ; 
                   SSL-Zertifikate verifizieren ; cURL-Optionen: $curl ]

Das PHP-Skript wiederum nimmt die hochgeladene PDF entgegen, übergibt sie an horstoeko und liefert ein strukturiertes JSON zurück:

{
    "ok": true,
    "mode": "raw",
    "file": "/www/htdocs/w01da32b/maps.maro-testserver.de/mc/uploads/upload.pdf",
    "data": {
        "profile": "EN16931",
        "profileId": 2,
        "invoiceNumber": "INV-2025-001",
        "typeCode": "380",
        "issueDateTime": "2025-08-01 18:57:53",
        "currency": "EUR",
        "taxCurrency": null,
        "language": null,
        "isCopy": false,
        "isTest": false,
        "seller": {
            "name": "MaRo-Programmierung GbR",
            "globalId": "16547",
            "description": "Birkenwerder",
            "address": {
                "lineOne": null,
                "lineTwo": null,
                "lineThree": null,
                "postCode": null,
                "city": null,
                "country": null,
                "subdivision": null
            }
        },
        "buyer": {
            "name": "Fensterhaus Ansbach GmbH",
            "globalId": "91522",
            "description": "Ansbach",
            "address": {
                "lineOne": null,
                "lineTwo": null,
                "lineThree": null,
                "postCode": null,
                "city": null,
                "country": null,
                "subdivision": null
            }
        },
        "totals": {
            "grandTotal": 1249.5,
            "duePayable": 1249.5,
            "lineTotal": 1050,
            "taxTotal": 199.5,
            "taxBasisTotal": 1050,
            "chargeTotal": null,
            "allowanceTotal": null,
            "roundingAmount": null,
            "totalPrepaidAmount": null
        },
        "payment": {
            "typeCode": "58",
            "information": null,
            "payeeIban": "DE12345678901234567890",
            "payeeBic": "GENODEF1XYZ",
            "accountName": "Testbank",
            "buyerIban": null,
            "cardType": null,
            "cardId": null,
            "cardHolderName": null
        },
        "tax": [
            {
                "categoryCode": "S",
                "typeCode": "VAT",
                "basisAmount": 1050,
                "calculatedAmount": 199.5,
                "rateApplicablePercent": 19,
                "exemptionReason": null,
                "exemptionReasonCode": null,
                "lineTotalBasisAmount": 0,
                "allowanceChargeBasisAmount": 0,
                "taxPointDate": null,
                "dueDateTypeCode": null
            }
        ],
        "lines": [
            {
                "lineId": "1",
                "name": "Entwicklung und Anpassungen",
                "description": null,
                "sellerId": null,
                "buyerId": null,
                "globalIdType": null,
                "globalId": null,
                "quantity": 10,
                "unitCode": "HUR",
                "unitPrice": 90,
                "netAmount": 900,
                "basisQuantity": null,
                "basisQuantityUnitCode": null,
                "chargeFreeQuantity": null,
                "chargeFreeQuantityUnitCode": null,
                "allowanceChargeAmount": null,
                "taxPercent": 19,
                "taxCategory": "S",
                "taxTypeCode": "VAT",
                "taxCalculatedAmount": null,
                "allTaxes": [
                    {
                        "categoryCode": "S",
                        "typeCode": "VAT",
                        "rateApplicablePercent": 19,
                        "calculatedAmount": null,
                        "exemptionReason": null,
                        "exemptionReasonCode": null
                    }
                ]
            },
            {
                "lineId": "2",
                "name": "Remote-Support pauschal",
                "description": null,
                "sellerId": null,
                "buyerId": null,
                "globalIdType": null,
                "globalId": null,
                "quantity": 1,
                "unitCode": "C62",
                "unitPrice": 150,
                "netAmount": 150,
                "basisQuantity": null,
                "basisQuantityUnitCode": null,
                "chargeFreeQuantity": null,
                "chargeFreeQuantityUnitCode": null,
                "allowanceChargeAmount": null,
                "taxPercent": 19,
                "taxCategory": "S",
                "taxTypeCode": "VAT",
                "taxCalculatedAmount": null,
                "allTaxes": [
                    {
                        "categoryCode": "S",
                        "typeCode": "VAT",
                        "rateApplicablePercent": 19,
                        "calculatedAmount": null,
                        "exemptionReason": null,
                        "exemptionReasonCode": null
                    }
                ]
            }
        ]
    }
}

Dieses JSON ist das ideale Bindeglied: In FileMaker genügt ein Loop über data.lines[], um die einzelnen Positionen anzulegen. Kopf und Summenfelder lassen sich direkt in Variablen schreiben und anschließend auf beliebige Felder mappen.

Warum das spannend ist • Automatisierte Buchung: Eingehende Lieferantenrechnungen können ohne Medienbruch erfasst werden. • Plausibilitätsprüfung: Brutto = Netto + Steuer lässt sich sofort abgleichen. • Flexibilität: Egal ob Erzeugung oder Import dieselbe Technik (PHP + horstoeko) kann beides.

Fazit

Während viele nur an die Ausgabe denken, ist gerade das Einlesen der eigentliche Schlüssel zur durchgängigen Digitalisierung von Rechnungsprozessen. Mit ZUGFeRD lassen sich Daten beidseitig austauschen und mit ein paar Skriptzeilen in FileMaker hat man plötzlich nicht nur ein Export, sondern auch eine Import-Funktion in der Hand.


Endlich ist es fertig: ZUGFeRD in FileMaker – Integration in unter einer Stunde

ZUGFeRD UBL.

Nach intensiver Entwicklung ist es soweit: Unser ZUGFeRD-/Factur-X Add-on für FileMaker ist fertig! 🎉 Wer schon einmal versucht hat, ZUGFeRD in eine FileMaker-Anwendung einzubauen, kennt die Herausforderung: Eigenentwicklungen ziehen sich über Tage oder Wochen, kosten Zeit, Geld und Nerven – und am Ende bleibt die Frage nach der Wartbarkeit.

Mit unserem Add-on gehen wir einen anderen Weg. Keine Programmierung, kein kompliziertes Skripten, stattdessen Mapping.

Mapping statt Programmieren

Die Implementierung basiert auf dem offiziellen COMFORT-Profil von ZUGFeRD/Factur-X. Das bedeutet: Alle relevanten Rechnungsdaten werden abgedeckt, ohne dass man sich selbst tief in Spezifikationen und Normdetails einarbeiten muss.

Anstatt eigene Scripts oder Datenmodelle zu schreiben, werden die bestehenden Felder in FileMaker einfach über ein Mapping den benötigten ZUGFeRD-Feldern zugeordnet. Damit bleibt die eigene Struktur unverändert, und trotzdem erfüllt die Anwendung sofort den Standard.

In weniger als einer Stunde einsatzbereit

Der größte Vorteil: Die Integration dauert in der Regel nicht länger als eine Stunde. Das Add-on klinkt sich direkt in die bestehende FileMaker-Datenbank ein, ohne dass das Rechnungslayout oder vorhandene Scripts angepasst werden müssen.

Wer möchte, kann die Integration jederzeit durch eigenes Skripting erweitern – doch die Grundinstallation läuft komplett ohne Programmieraufwand.

Vorteile gegenüber Eigenentwicklung • Zeitersparnis: statt tagelanger Arbeit → unter einer Stunde fertig. • Kostenreduktion: keine teuren Eigenentwicklungen, kein externer Entwickler notwendig. • Zukunftssicherheit: Nutzung des offiziellen ZUGFeRD-COMFORT-Profils, das in vielen Branchen bereits Standard ist. • Flexibilität: Erweiterungen und Anpassungen sind jederzeit möglich, aber nicht zwingend nötig.

Fazit

Endlich verfügbar! Mit unserem ZUGFeRD-Add-on für FileMaker sparen Sie Zeit, Geld und Ressourcen – und bleiben dabei normenkonform.


ZUGFeRD mit PHP: Wie ich das horstoeko/zugferd-Paket lokal vorbereitet und ohne Composer-Zugriff auf den Server gebracht habe

Wer schon einmal versucht hat, das ZUGFeRD-Format mit PHP umzusetzen, wird früher oder später auf das Projekt horstoeko/zugferd stoßen. Es bietet eine mächtige Möglichkeit, ZUGFeRD-konforme Rechnungsdaten zu erstellen und in PDF-Dokumente einzubetten. Doch gerade am Anfang lauern einige Stolpersteine: Composer, Pfadprobleme, Server ohne Shell-Zugriff. Dieser Beitrag zeigt, wie ich mir mit einem lokalen Setup, GitKraken und einem simplen Upload-Trick geholfen habe, um trotz aller Einschränkungen produktiv arbeiten zu können.

Bevor ich das Paket überhaupt einbinden konnte, musste Composer einmal lokal installiert werden – ganz ohne kommt man nicht aus. Ich habe mich für den Weg über die offizielle Installationsanleitung entschieden:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"

Es gibt aber auch fertige Pakete als *.exe für Windows.

GitKraken, Composer & das Terminal

Ich arbeite gerne visuell, und daher ist GitKraken mein bevorzugter Git-Client. Doch ein oft unterschätzter Vorteil: GitKraken bringt ein eigenes Terminal mit. Dieses habe ich genutzt, um Composer lokal zu verwenden – ohne die globale Composer-Installation auf meinem Server-System anfassen zu müssen.

Bildschirmfoto 2025-04-23 um 15.55.21.
# Im Terminal von GitKraken
composer require horstoeko/zugferd

Dabei habe ich mich bewusst für die 1.x-Version entschieden, da diese eine stabilere und besser dokumentierte Grundlage für den Einsatz ohne komplexes Setup bietet. Zudem ist dort der ZugferdDocumentPdfBuilder enthalten, der es erlaubt, das gesamte PDF-Handling im PHP-Kosmos zu belassen. Soweit ich gesehen habe, gibt es wohl auch DEV-Versionen, aber ich war mir nicht sicher wie weit diese nutzbar sind.

Der Upload-Trick: Alles lokal vorbereiten

Da mein Zielserver keinen Composer-Zugriff bietet, musste ich alles lokal vorbereiten. Ich nutze für meine Testumgebung einen einfachen Server von AllInk. Das ist extrem kostengünstig, aber eigene Software installieren, Fehlanzeige. Der Trick: Ich habe den gesamten vendor-Ordner inklusive composer.json und composer.lock gezippt und manuell auf den Server übertragen. Das spart nicht nur Zeit, sondern funktioniert in jeder Hostingumgebung.

# Lokaler Aufbau
my-project/
├── src/
├── vendor/
├── composer.json
├── composer.lock

Dann per SFTP oder FTP hochladen und sicherstellen, dass im PHP-Code folgender Autoloader korrekt eingebunden wird:

require __DIR__ . '/vendor/autoload.php';

Vorsicht, Pfade: Die Sache mit dem “/src”-Unterordner

Ein Stolperstein war die Struktur des horstoeko-Pakets. Die Klassen liegen nicht direkt im Projektverzeichnis, sondern verstecken sich unter:

/vendor/horstoeko/zugferd/src/...

Der PSR-4-Autoloader von Composer ist darauf vorbereitet, aber wer manuell Klassen einbindet oder den Autoloader nicht korrekt referenziert, bekommt Fehler. Ein Test mit:

use horstoeko\zugferd\ZugferdDocumentPdfBuilder;

funktionierte erst, nachdem ich sicher war, dass der Autoloader geladen war und keine Pfade fehlten.

Endlich produktiv: Der erste Builder-Lauf

Nachdem alles hochgeladen und die Autoloading-Probleme beseitigt waren, konnte ich mein erstes ZUGFeRD-Dokument bauen:

$builder = new ZugferdDocumentPdfBuilder();
$builder->setDocumentFile("./rechnung.pdf");
$builder->setZugferdXml("./debug_12345.xml");
$builder->saveDocument("./zugferd_12345_final.pdf");

Und siehe da: eine ZUGFeRD-konforme PDF-Datei, direkt aus PHP erzeugt. Kein Java, kein PDF/A-Tool von Adobe, keine Blackbox. Wichtig, das ganze ist per ZIP auf jeden Kundenserver übertragbar.

Warum kein Java?

Ich habe bewusst darauf verzichtet, Java-Tools wie Apache PDFBox oder gar die offizielle ZUGFeRD Java Library zu nutzen – aus einem ganz einfachen Grund: Ich wollte die Lösung so nah wie möglich an meiner bestehenden PHP-Infrastruktur halten. Keine zusätzliche Runtime, keine komplexen Abhängigkeiten, keine Übersetzungsprobleme zwischen Systemen. PHP allein reicht – wenn man die richtigen Werkzeuge nutzt.

Häufige Fehlermeldungen und ihre Lösungen

Gerade beim Einstieg in das horstoeko/zugferd-Paket können einige typische Fehlermeldungen auftreten:

Fehler: Class 'horstoeko\zugferd\ZugferdDocumentPdfBuilder' not found

// Lösung:
require_once __DIR__ . '/vendor/autoload.php';

Fehler: Cannot open file ./debug_12345.xml

// Lösung:
Pfad prüfen! Gerade bei relativen Pfaden kann es helfen, alles absolut zu machen:
$builder->setZugferdXml(__DIR__ . '/debug_12345.xml');

Fehler: Output file cannot be written

// Lösung:
Schreibrechte auf dem Zielverzeichnis prüfen! Ein chmod 775 oder 777 (mit Bedacht!) kann helfen.

Fazit: Wer wie ich auf Servern ohne Composer arbeiten muss oder will, kann sich mit einem lokalen Setup, GitKraken und einem Zip-Upload wunderbar behelfen. Wichtig ist, auf die Pfade zu achten, den Autoloader korrekt einzubinden und nicht vor kleinen Hürden zurückzuschrecken. Die Möglichkeiten, die das horstoeko/zugferd-Paket bietet, machen die Mühe mehr als wett.

Zumal das ganze Setup, 1 zu 1, auf einen Kundenserver übertragen werden kann. Die eigentlichen Daten kommen aus FileMaker, dieser holt sich die PDF und das XML auch wieder vom Server ab. Somit ist die Erstellung der ZUGFeRD-PDF und der XML mit einen FileMaker-Script abzudecken. Für die Erstellung auf dem Server bedarf es zweier PHP-Scripte. Dazu das Horstoeko/zugferd-Paket.


ZUGFeRD mit horstoeko/zugferd und FileMaker

Bildschirmfoto 2025-04-17 um 13.55.33.

Nach unzähligen Versuchen mit TCPDF, FPDI und verschiedensten Merge-Strategien, habe ich mich letztlich für einen pragmatischeren Weg entschieden: Ich lasse sowohl das PDF als auch das XML direkt auf dem Server erzeugen – ohne nachträglichen Merge. Die Lösung basiert auf dem PHP-Paket horstoeko/zugferd, welches sich nach einigen Stolpersteinen als zuverlässig herausgestellt hat – sobald man seine Eigenheiten akzeptiert.

Im ersten Szenario habe ich die fertige PDF aus FileMaker auf den Server, dort dann die Daten als POST-Parameter empfangen. Dann versucht die beiden Dateien, XML und PDF zu verschmelzen. Keine Change, bin fast verzweifelt, kenne die Doku zu Horstoeko/Zugferd aus dem FF. Aber es hat nicht geklappt. Also jetzt der pragmatische Ansatz. Die Daten werden übertragen und dann wird auf dem Server alles erzeugt.

Der FileMaker-Teil übergibt die notwendigen Daten per POST an ein PHP-Skript auf dem Server. Dieses Skript generiert daraus die ZUGFeRD-konforme XML, erzeugt gleichzeitig ein einfaches PDF mit den wichtigsten Rechnungsdaten (z. B. Rechnungstitel, Nummer etc.) – und bindet die XML direkt beim Erzeugen ein. Kein nachträgliches Anhängen mehr nötig. Kein Merge-Objekt, kein Zwischenschritt. Die erzeugte Datei ist PDF/A-3B und enthält die eingebettete Rechnung als XML. Dabei wird die PDF gleich im PHP etwas angepasst. Vermutlich wird das ganze noch etwas schicker mit css Implementierung, aber für den Anfang reicht es so.

Hier ist der komplette PHP-Code, den ich aktuell produktiv im Testsystem einsetze:

 $_POST['sellerName'] ?? '',
		'street' => $_POST['sellerStreet'] ?? '',
		'zip' => $_POST['sellerPostalCode'] ?? '',
		'city' => $_POST['sellerCity'] ?? '',
		'country' => $_POST['sellerCountryCode'] ?? 'DE',
		'tax_id' => $_POST['sellerTaxID'] ?? ''
	];
	
	// Rechnungsempfänger-Daten
	$buyer = [
		'name' => $_POST['buyerName'] ?? '',
		'street' => $_POST['buyerStreet'] ?? '',
		'zip' => $_POST['buyerPostalCode'] ?? '',
		'city' => $_POST['buyerCity'] ?? '',
		'country' => $_POST['buyerCountryCode'] ?? 'DE',
		'tax_id' => $_POST['buyerTaxID'] ?? ''
	];
	
	// Zahlungsinformationen
	$payment = [
		'means_code' => $_POST['paymentMeansCode'] ?? '',
		'financial_institution' => $_POST['payeeFinancialInstitution'] ?? '',
		'iban' => $_POST['payeeIBAN'] ?? '',
		'bic' => $_POST['payeeBIC'] ?? '',
		'reference' => $_POST['paymentReference'] ?? ''
	];
	
	// Steuerinformationen
	$tax = [
		'rate' => floatval(str_replace(',', '.', $_POST['taxRate'] ?? '19')),
		'amount' => floatval(str_replace(',', '.', $_POST['taxAmount'] ?? '0')),
		'taxable_amount' => floatval(str_replace(',', '.', $_POST['taxableAmount'] ?? '0')),
		'category_code' => $_POST['taxCategoryCode'] ?? 'S'
	];
	
	// Positionen aus lineItemsRaw extrahieren
	$positions = [];
	$lineItems = explode('|', $_POST['lineItemsRaw'] ?? '');
	
	foreach ($lineItems as $lineItem) {
		if (empty($lineItem)) continue;
		
		$parts = explode(';', $lineItem);
		if (count($parts) >= 7) {
			$quantity = floatval($parts[3]);
			$netPrice = floatval(str_replace(',', '.', $parts[5]));
			$total = $quantity * $netPrice;
			$orderDate = isset($parts[8]) ? date('d.m.Y', strtotime($parts[8])) : '';
			
			$positions[] = [
				'position' => $parts[0],
				'description' => $parts[1],
				'article_number' => $parts[2],
				'quantity' => $quantity,
				'unit' => $parts[4],
				'net_price' => $netPrice,
				'tax_rate' => floatval($parts[6]),
				'total' => $total,
				'order_date' => $orderDate
			];
		}
	}
	
	// Summen neu berechnen
	$totalNet = 0;
	$totalTax = 0;
	
	foreach ($positions as $position) {
		$totalNet += $position['total'];
		$totalTax += $position['total'] * ($position['tax_rate'] / 100);
	}
	
	$totals = [
		'net' => $totalNet,
		'tax' => $totalTax,
		'gross' => $totalNet + $totalTax
	];
	
	// Pfade definieren
	$pdfPath = $uploadDir . $invoiceNumber . '.pdf';
	$xmlPath = $uploadDir . 'inv_' . $invoiceNumber . '.xml';
	$outputPath = $uploadDir . $invoiceNumber . '_ZUGFeRD.pdf';

	// PDF-Datei überprüfen
	if (!checkFile($pdfPath, "PDF-Datei")) {
		throw new Exception("PDF-Datei nicht verfügbar");
	}

	// ZUGFeRD-Dokument erstellen
	logMessage("Erstelle ZUGFeRD-Dokument...");
	$document = ZugferdDocumentBuilder::createNew(ZugferdProfiles::PROFILE_BASIC);
	logMessage("DocumentBuilder initialisiert");

	// Basisinformationen setzen
	logMessage("Setze Basisinformationen...");
	$document->setDocumentInformation(
		$invoiceTypeCode,                    // Dokumenttyp (380 = Rechnung)
		$invoiceNumber,                    // Rechnungsnummer
		new DateTime($invoiceDate),        // Rechnungsdatum
		$currency                          // Währung
	);
	logMessage("Basisinformationen gesetzt");

	// Rechnungssteller setzen
	logMessage("Setze Rechnungssteller...");
	$document->setDocumentSeller(
		$seller['name'],                   // Name
		$seller['zip'],                    // PLZ
		$seller['city'],                   // Stadt
		$seller['street'],                 // Straße
		$seller['country']                 // Land
	);
	logMessage("Rechnungssteller gesetzt");

	// Rechnungsempfänger setzen
	logMessage("Setze Rechnungsempfänger...");
	$document->setDocumentBuyer(
		$buyer['name'],                    // Name
		$buyer['zip'],                     // PLZ
		$buyer['city'],                    // Stadt
		$buyer['street'],                  // Straße
		$buyer['country']                  // Land
	);
	logMessage("Rechnungsempfänger gesetzt");

	// Positionen hinzufügen
	logMessage("Füge Positionen hinzu...");
	foreach ($positions as $index => $position) {
		$document->addNewPosition((string)($index + 1));
		$document->setDocumentPositionProductDetails($position['description']);
		$document->setDocumentPositionNetPrice($position['net_price']);
		$document->setDocumentPositionQuantity($position['quantity'], $position['unit']);
		$document->addDocumentPositionTax("S", "VAT", $position['tax_rate']);
		$document->setDocumentPositionLineSummation($position['total']);
		logMessage("Position {$position['description']} hinzugefügt");
	}
	
	// PDF mit Rechnungsdaten erstellen
	logMessage("🔄 Erstelle PDF mit Rechnungsdaten...");
	try {
		$pdf = new FPDF();
		$pdf->AddPage();
		$pdf->SetAutoPageBreak(true, 20);
		
		// Schriftarten definieren
		$pdf->SetFont('Arial', '', 10);
		
		// Absenderadresse
		$pdf->SetXY(20, 20);
		$pdf->Cell(0, 5, $seller['name'], 0, 1);
		$pdf->Cell(0, 5, 'GmbH & Co. KG', 0, 1);
		$pdf->Cell(0, 5, $seller['street'], 0, 1);
		$pdf->Cell(0, 5, 'D-' . $seller['zip'] . ' ' . $seller['city'], 0, 1);
		
		// Rechnungsinformationen rechts oben
		$pdf->SetXY(120, 20);
		$pdf->SetFont('Arial', '', 9);
		
		// Rechte Spalte mit Informationen
		$rightColumnData = [
			['Nummer', $invoiceNumber],
			['Datum', date('d.m.Y', strtotime($invoiceDate))],
			['Kunden Nr.', $_POST['customerNumber'] ?? '16105'],
			['Lieferschein', $_POST['deliveryNote'] ?? ''],
			['Lief. Datum', date('d.m.Y', strtotime($_POST['deliveryDate'] ?? $invoiceDate))]
		];
		
		foreach ($rightColumnData as $row) {
			$pdf->SetX(120);
			$pdf->Cell(30, 5, $row[0], 0, 0);
			$pdf->Cell(40, 5, $row[1], 0, 1);
		}
		
		// Überschrift "Rechnung"
		$pdf->SetFont('Arial', '', 14);
		$pdf->SetXY(20, 70);
		$pdf->Cell(0, 10, 'Rechnung', 0, 1);
		
		// Positionen Header
		$pdf->SetFont('Arial', '', 8);
		$pdf->SetFillColor(240, 240, 240);
		$pdf->SetY($pdf->GetY() + 5);
		
		// Spaltenbreiten
		$colWidths = [
			'auftrag' => 25,
			'bestellung' => 35,
			'kommission' => 35,
			'artikel' => 25,
			'bezeichnung' => 60,
			'menge' => 20,
			'preis' => 25,
			'gesamt' => 25
		];
		
		// Positionen ausgeben
		foreach ($positions as $index => $position) {
			// Grauer Balken für Auftragskopf
			$pdf->SetFillColor(240, 240, 240);
			$y = $pdf->GetY();
			
			// Auftragskopf mit Datum
			$pdf->Cell($colWidths['auftrag'], 5, 'Auftrag: ' . $position['article_number'] . ' / ' . $position['order_date'], 0, 0, 'L', true);
			$pdf->Cell($colWidths['bestellung'], 5, 'Ihre Bestellung: ' . $_POST['orderNumber'], 0, 0, 'L', true);
			$pdf->Cell($colWidths['kommission'], 5, 'Ihre Kommission:', 0, 1, 'L', true);
			
			// Positionsdetails
			$pdf->SetFont('Arial', '', 8);
			$pdf->Cell($colWidths['artikel'], 5, $position['article_number'], 0, 0);
			$pdf->Cell($colWidths['bezeichnung'], 5, $position['description'], 0, 0);
			$pdf->Cell($colWidths['menge'], 5, $position['quantity'] . ' ' . $position['unit'], 0, 0, 'R');
			$pdf->Cell($colWidths['preis'], 5, number_format($position['net_price'], 2, ',', '.') . ' €', 0, 0, 'R');
			$pdf->Cell($colWidths['gesamt'], 5, number_format($position['total'], 2, ',', '.') . ' €', 0, 1, 'R');
			
			$pdf->Ln(2);
		}
		
		// Summen am Ende
		$pdf->SetY(-60);
		$pdf->SetFont('Arial', '', 9);
		
		// Zahlungsbedingungen
		$pdf->Cell(0, 5, 'Rechnungsbetrag zahlbar bis ' . date('d.m.Y', strtotime($dueDate)), 0, 1);
		$pdf->Cell(0, 5, 'Bei Zahlung bis ' . date('d.m.Y', strtotime($dueDate)) . ' Skonto 3 %', 0, 1);
		
		// Summen rechtsbündig
		$pdf->SetX(-80);
		$pdf->Cell(30, 5, 'Summe netto', 0, 0, 'R');
		$pdf->Cell(50, 5, number_format($totals['net'], 2, ',', '.') . ' €', 0, 1, 'R');
		
		$pdf->SetX(-80);
		$pdf->Cell(30, 5, 'USt. ' . number_format($tax['rate'], 0) . ' %', 0, 0, 'R');
		$pdf->Cell(50, 5, number_format($totals['tax'], 2, ',', '.') . ' €', 0, 1, 'R');
		
		$pdf->SetX(-80);
		$pdf->SetFont('Arial', 'B', 9);
		$pdf->Cell(30, 5, 'Rechnungsbetrag', 0, 0, 'R');
		$pdf->Cell(50, 5, number_format($totals['gross'], 2, ',', '.') . ' €', 0, 1, 'R');
		
		// Bestellnummer
		$pdf->SetFont('Arial', '', 9);
		$pdf->SetY(-30);
		$pdf->Cell(0, 5, 'Zu Kommission:        Bestell-Nr.: ' . ($_POST['orderReference'] ?? ''), 0, 1);
		
		// Horizontale Linie am Ende
		$pdf->SetY(-20);
		$pdf->Line(20, $pdf->GetY(), 190, $pdf->GetY());
		
		$pdf->Output('F', $outputPath);
		logMessage("PDF erfolgreich generiert: $outputPath");
		
		if (file_exists($outputPath)) {
			logMessage("ZUGFeRD-PDF erfolgreich erstellt: " . basename($outputPath));
			logMessage("Dateigröße: " . filesize($outputPath) . " Bytes");
		} else {
			throw new Exception("ZUGFeRD-PDF wurde nicht erstellt!");
		}
	} catch (Exception $e) {
		logMessage(" Fehler beim PDF-Generieren: " . $e->getMessage());
		logMessage(" Stack Trace:\n" . $e->getTraceAsString());
		throw $e;
	}

} catch (Exception $e) {
	logMessage(" Fehler beim Erstellen der ZUGFeRD-PDF: " . $e->getMessage());
	logMessage(" Stack Trace:\n" . $e->getTraceAsString());
	
	// Debug-Informationen
	logMessage("\nDebug-Informationen:");
	logMessage("PHP Version: " . PHP_VERSION);
	logMessage("Memory Limit: " . ini_get('memory_limit'));
	logMessage("Max Execution Time: " . ini_get('max_execution_time'));
	logMessage("Upload Directory Permissions: " . substr(sprintf('%o', fileperms($uploadDir)), -4));
	
	// XML-Datei prüfen
	if (file_exists($xmlPath)) {
		logMessage("XML-Datei existiert: " . filesize($xmlPath) . " Bytes");
		logMessage("XML-Inhalt (erste 200 Zeichen):\n" . substr(file_get_contents($xmlPath), 0, 200));
	} else {
		logMessage("XML-Datei existiert nicht");
	}
}

Natürlich ist das so erst der Anfang, so fehlt die Überprüfung des fertigen PDF-A, aber bei händischen Tests, wurde alles akzeptiert.

Die Vorgehensweise aus FileMaker heraus ist klar. Daten sammeln und als POST übertragen. Der POST schaut in etwa so aus. Aus URL einfügen:

“-X POST " & “–header "Content-Type: application/x-www-form-urlencoded" " & “–data " & Zitat ( “invoiceNumber=” & $invoiceNumber & “&invoiceDate=” & $invoiceDate & “&invoiceCurrencyCode=” & $invoiceCurrencyCode & “&invoiceTypeCode=” & $invoiceTypeCode & “&dueDate=” & $dueDate & “&paymentTerms=” & $paymentTerms & “&deliveryTerms=” & $deliveryTerms &

“&sellerName=” & $sellerName & “&sellerStreet=” & $sellerStreet & “&sellerPostalCode=” & $sellerPostalCode & “&sellerCity=” & $sellerCity & “&sellerCountryCode=” & $sellerCountryCode & “&sellerTaxID=” & $sellerTaxID &

“&buyerName=” & $buyerName & “&buyerStreet=” & $buyerStreet & “&buyerPostalCode=” & $buyerPostalCode & “&buyerCity=” & $buyerCity & “&buyerCountryCode=” & $buyerCountryCode & “&buyerTaxID=” & $buyerTaxID &

“&paymentMeansCode=” & $paymentMeansCode & “&payeeFinancialInstitution=” & $payeeFinancialInstitution & “&payeeIBAN=” & $payeeIBAN & “&payeeBIC=” & $payeeBIC & “&paymentReference=” & $paymentReference &

“&taxRate=” & $taxRate & “&taxAmount=” & $taxAmount & “&taxableAmount=” & $taxableAmount & “&taxCategoryCode=” & $taxCategoryCode &

“&totalNetAmount=” & $totalNetAmount & “&totalTaxAmount=” & $totalTaxAmount & “&totalGrossAmount=” & $totalGrossAmount & “&lineItemsRaw=” & $lineItemsRaw

) Bildschirmfoto 2025-04-17 um 13.53.50.

Nun geht es darum, die Form der Rechnung anzupassen, die Rechnung schon auf dem System zu validieren. Im Anschluss muss diese wieder im FileMaker-System zugänglich sein. Was ich aber jetzt schon sagen kann, es geht auch ohne MBS-Plugin und ohne die dort auflaufenden Lizenz-Kosten. Der Weg bis zu diesem Punkt war wirklich sehr steinig, vieles funktionierte nicht so wie dokumentiert. Jetzt bin ich froh,


PDF-Erzeugung per IWP

Jeder der eine Datenbank im Web über IWP freigibt, kommt irgendwann an einen Punkt wo er die Entscheidung IWP zu verwenden bereut.

Nun ich erreichte den Punkt als es darum ging Dateien zu exportieren, oder nur eine PDF zu erzeugen. Viele Script-Schritte funktionieren über IWP nicht. Kein als Excel-Speichern, kein Datensätze als PDF speichern.

Was also tun wenn man z.B. Teilnehmer über IWP erfassen möchte und Diese im Anschluss eine Anmeldebestätigung erhalten sollen?

Die Antwort habe ich im FileMaker-Forum erhalten. Einfach einen Client auf dem Server mitlaufen lassen. Einen Client auf dem Server laufen lassen?

Was steckt dahinter. Nun der Client übernimmt die Aufgaben die der Server nicht kann. Also speichern, exportieren oder gar importieren von Dateien. Alles was eine Client im Netzwerk kann, geht mit diesem Ansatz.

Wie aber sage ich nun dem Client was zu tun ist? Über gesetzte Feldwerte. Die Funktion Feldwert setzen geht auch über IWP basierte Webseiten. Das bedeutet z.B. wenn die Anmeldung eines Teilnehmers durchlaufen ist, wird über ein Script der Feldwert „FLAG.MAIL.Anmeldung_1“ auf den Wert 1 gesetzt.

Jetzt beginnt die Arbeit des Clients. Über ein „BeiTimer-Script“ setzen überprüft der Client regelmäßig ob der Feldwert „FLAG.MAIL.Anmeldung_1“ den Wert 1 enthält. Tut er dies, wird einfach ein Script zu Versenden einer EMail angestossen. Um nun nicht im Minutentakt immer wieder eine Mail an den Teilnehmer zu versenden gibt es noch ein zweites Statusfeld. Dieses erhält nach Versendung der Mail den Status 1. Ist der Wert dieses Feldes auf 1, wird keine Mail versendet.

Auf diese Weise kann ich alle Funktionen die ein Client beherrscht auch über den Server ansteuern.