Zum Hauptinhalt springen

ArtinTech Solution

WordPress invoice plugin by ArtinTech Solution

🌐 Diesen Artikel in einer anderen Sprache lesen: English · Español · Deutsch · Français · العربية · Bahasa Melayu · 简体中文 · 日本語

Die meisten kleinen Agenturen und Freelancer schreiben ihre Rechnungen auf eine von zwei Arten. Entweder mit einer Tabelle und einer Word-Vorlage, die jemand von Hand als PDF exportiert. Oder mit einem gehosteten Rechnungsdienst, der pro Nutzer und Monat abgerechnet wird, ohne Ende. Die erste Variante bricht zusammen, sobald zwei Personen damit arbeiten. Die zweite funktioniert gut, bis ein Teammitglied, eine zweite Währung oder ein Kunde hinzukommt, der etwas braucht, wofür das Produkt nie gedacht war.

Wir hatten beide Probleme, also haben wir unser eigenes WordPress Rechnungs-Plugin gebaut: ArtinTech Invoice Manager. Es läuft als Vollbild-Anwendung auf einer WordPress-Website. Es erstellt professionelle Rechnungen mit PDF-Export per Klick, führt eine Kundenkartei mit offenen Beträgen, verfolgt Zahlungen in mehreren Währungen und bietet einen Admin-Bereich zur Verwaltung der Nutzer. Das Plugin ist auf dieser Website im Einsatz, und wir stellen damit heute unseren eigenen Kunden Rechnungen.

Dieser Artikel ist das vollständige Entwicklungsprotokoll. Er zeigt, was das Plugin kann, wie es aufgebaut ist und warum, wie das Sicherheitskonzept aussieht, welche Fehler wir gefunden haben, bevor unsere Kunden sie bemerkten, und was nötig war, um den Code für das Plugin-Verzeichnis von WordPress.org vorzubereiten. Wenn Sie überlegen, ob Sie ein individuelles Rechnungstool bauen lassen oder ein fertiges nutzen, sind die letzten Abschnitte für Sie geschrieben.

Dashboard des WordPress Rechnungs-Plugins mit Summen für berechnet, eingegangen, offen und überfällig
Das Rechnungs-Dashboard: Summen je Währung, aktuelle Rechnungen und die vollständige Liste. Alle Screenshots in diesem Artikel zeigen Demodaten, die Kundennamen sind frei erfunden.

Warum wir ein eigenes WordPress Rechnungs-Plugin gebaut haben

Software selbst zu bauen, die man mieten könnte, ist meistens ein Fehler. Deshalb lohnt es sich, genau zu begründen, warum es hier keiner war. Die ausschlaggebenden Gründe waren praktischer, nicht ideologischer Natur.

  • Die Daten gehören ins eigene Unternehmen. Rechnungen, Kundenadressen und Zahlungshistorie sind die finanzielle Dokumentation eines Unternehmens. Sie in derselben WordPress-Datenbank zu halten, die wir ohnehin sichern und kontrollieren, ist einfacher, als am Tag X auf den Export-Button eines Drittanbieters angewiesen zu sein.
  • Preise pro Nutzer skalieren gegen Sie. Ein gehostetes Tool, das für eine Person günstig ist, wird zu einem echten Kostenfaktor, sobald ein kleines Team und einige externe Mitarbeiter eigene Zugänge brauchen. Ein Plugin kostet dasselbe, ob es eine Person nutzt oder zwanzig.
  • Mehrere unabhängige Kontoinhaber, eine Installation. Jede Person sollte eigene Rechnungen, Kunden, ein eigenes Logo, eigene Bankdaten und eine eigene Nummerierung haben, vollständig getrennt von allen anderen, auf einer einzigen Website.
  • Unsere Rechnungen sind international. Wir stellen Kunden im Ausland Rechnungen, in mehr als einer Währung. Wir brauchten Summen je Währung, ohne stillschweigende Umrechnung, und Rechnungen, die Bankdaten für Auslandsüberweisungen enthalten.
  • Wir wollten es selbst ändern können. Als wir einen Button „Als bezahlt markieren“ oder einen Schalter zum Ausblenden des Kundenlogos brauchten, wollten wir ihn am selben Nachmittag, nicht irgendwann auf der Roadmap eines Anbieters.

Das alles macht gehostete Rechnungssoftware nicht schlecht. Es ist eine andere Abwägung, und ein direkter Vergleich hilft.

Gehosteter RechnungsdienstSelbst gehostetes WordPress Rechnungs-Plugin
Speicherort der DatenServer des AnbietersIhre eigene WordPress-Datenbank
Kosten bei wachsendem TeamSteigen meist pro NutzerFix, unabhängig von der Nutzerzahl
EinrichtungsaufwandMinutenInstallieren, aktivieren, App-Seite anlegen
AnpassbarkeitWas die Einstellungen erlaubenAlles, was der Code kann
WartungÜbernimmt der AnbieterIhre Verantwortung, wie bei jedem Plugin
IntegrationenOft ein großer Katalog fertiger KonnektorenNach Bedarf für Ihre eigene Systemlandschaft gebaut

Wenn sich die rechte Spalte wie eine Liste lästiger Pflichten liest, ist ein gehostetes Tool für Sie vermutlich die bessere Wahl. Wenn sie sich wie eine Liste von Dingen liest, die Sie für Ihre Website ohnehin erledigen, wird ein Plugin interessant.

So funktioniert es: von der Installation bis zur bezahlten Rechnung

Vor den Details hier der komplette Ablauf von Anfang bis Ende: was ein Administrator einmalig erledigt und was ein Kontoinhaber bei jeder Rechnung tut. Neun Schritte, jeweils an der echten Oberfläche gezeigt.

Schritt 1: Plugin installieren und App-Seite anlegen

  1. Laden Sie das Plugin unter Plugins → Add New → Upload Plugin hoch und aktivieren Sie es.
  2. Öffnen Sie das neue Menü Invoice Manager in wp-admin.
  3. Klicken Sie auf Create app page.

Damit wird eine Seite unter /invoice-manager/ veröffentlicht, und diese Seite ist die Anwendung. Sonst ändert sich nichts an der Website. Administratoren können die App sofort nutzen.

Schritt 2: Anmelden oder andere registrieren lassen

Die App-Seite zeigt allen, die nicht angemeldet sind, einen eigenen Login-Bildschirm. Die Anmeldung erfolgt mit dem normalen WordPress-Benutzernamen oder der E-Mail-Adresse, inklusive „Remember me“ und „Forgot password“.

Login-Bildschirm des Invoice Manager
Der Login im Frontend. Kontoinhaber müssen wp-admin nie sehen.

Wenn Sie die öffentliche Registrierung aktivieren, erscheint unter dem Login-Formular der Link Create one, der zur Registrierung führt. Ist die Admin-Freigabe eingeschaltet, bleibt ein neues Konto im Status „ausstehend“, bis ein Administrator es freigibt.

Registrierungsbildschirm des Invoice Manager
Die optionale Registrierung, mit dem Hinweis, dass neue Konten vor der Nutzung geprüft werden.

Schritt 3: Unternehmensdaten einmalig hinterlegen

Jeder Kontoinhaber beginnt unter My settings:

  • Logo hochladen und zwischen Einzelperson und Unternehmen wählen.
  • Adresse, Kontaktdaten und Steuernummer eintragen.
  • Standardwährung und Zahlungsziel festlegen.
  • Bankverbindung einfügen.
  • Rechnungspräfix und Startnummer festlegen und eigene Steuersätze anlegen.

Alles, was hier steht, wird automatisch in neue Rechnungen übernommen. Sie tippen es also nur einmal.

Kontoeinstellungen mit Logo, Firmenadresse, Währung, Bankverbindung und Rechnungsnummerierung
My settings: Branding, Unternehmensdaten, Währung, Bankverbindung und Rechnungsnummerierung.

Schritt 4: Kunden anlegen

Unter Clients → Add Client speichern Sie jeden Kunden einmalig: Logo, Firmen- und Ansprechpartnername, E-Mail, Telefon, Adresse und Steuernummer. Die Kundenkartei ist durchsuchbar, und jede Karte zeigt, wie viele Rechnungen ein Kunde hat und was noch offen ist.

Kundenkartei mit Logos und offenen Beträgen
Die Kundenkartei, mit Logos und offenen Beträgen auf einen Blick.

Schritt 5: Rechnung erstellen

Klicken Sie auf New invoice. Nummer, Datum, Währung, Bedingungen und Ihre Daten sind bereits ausgefüllt.

  1. Kunden auswählen.
  2. Positionen mit Menge, Preis und Steuersatz hinzufügen.
  3. Bei Bedarf einen Rabatt gewähren und eigene Felder ergänzen, etwa eine Bestellnummer.
  4. Festlegen, ob Ihr Logo und das Kundenlogo auf dieser Rechnung erscheinen.
  5. Auf Save klicken.

Die Summen werden während der Eingabe neu berechnet.

Rechnungseditor mit Positionen, Rabatt, Kundendaten und Logo-Schaltern
Der Rechnungseditor: links das Dokument, rechts die Aktionen und Logo-Schalter.

Schritt 6: Vorschau ansehen und PDF herunterladen

Preview zeigt die Rechnung genau so, wie der Kunde sie erhält. Download PDF speichert eine A4-Datei, die Sie per E-Mail versenden, in ein Kundenportal hochladen oder drucken können.

Drei Vorlagen stehen zur Wahl, einstellbar pro Rechnung über das Vorlagenmenü im Editor:

  • Blank: schlichtes, minimalistisches Layout.
  • Modern: farbiger Kopfbereich.
  • Classic: Serifenschrift mit Trennlinien.
PDF-Rechnungsvorschau mit Absender- und Kundenlogo, Bankverbindung und Zahlungsbedingungen
Die PDF-Vorschau, mit beiden Logos, Rabatt, Bankverbindung und Zahlungsbedingungen.

Schritt 7: Zahlung erfassen

Sobald das Geld eingeht, klicken Sie in der Zeile der Rechnung auf Mark paid, oder auf das $-Symbol, um eine Teilzahlung mit Datum, Zahlungsart und Referenz zu erfassen. Der Status ändert sich automatisch:

  • Partially paid (teilweise bezahlt) nach einer Teilzahlung.
  • Paid (bezahlt), sobald der offene Betrag null erreicht.
  • Overdue (überfällig), wenn das Fälligkeitsdatum verstreicht, bevor die Rechnung vollständig bezahlt ist.
Dialog zum Erfassen einer Zahlung mit Betrag, Datum und Zahlungsart
Eine Zahlung erfassen. Der Betrag ist mit dem offenen Saldo vorbelegt.

Schritt 8: Offene Posten im Blick behalten

Die Summen im Dashboard aktualisieren sich sofort. Für einen einzelnen Kunden öffnen Sie dessen Seite in der Kundenkartei und sehen dort:

  • Alles Berechnete, Eingegangene und Offene, je Währung.
  • Jede Rechnung, die Sie diesem Kunden gestellt haben.

Genau diesen Bildschirm öffnen Sie vor einem Nachfass-Telefonat.

Kundenseite mit berechneten, eingegangenen und offenen Summen sowie Rechnungshistorie
Die Kundenseite: Salden je Währung und vollständige Rechnungshistorie.

Schritt 9: Nutzer verwalten

Administratoren und alle mit der Rolle Invoice Manager Admin öffnen Admin panel → Users. Dort können sie:

  • Ausstehende Registrierungen freigeben. Der Nutzer wird automatisch per E-Mail benachrichtigt.
  • Konten sperren oder reaktivieren.
  • Nutzer direkt anlegen. Neue Nutzer erhalten eine E-Mail, um ihr Passwort festzulegen.
  • Rollen ändern und Konten löschen.
Nutzerverwaltung im Admin-Bereich mit Freigeben, Sperren und Rollensteuerung
Nutzerverwaltung: Freigaben, Sperrungen, Rollen sowie die Anzahl der Rechnungen und Kunden je Konto.

Was das Plugin kann: ein Funktionsrundgang

Der Ablauf oben zeigt den Hauptweg. Dieser Rundgang deckt den Rest ab. Alles läuft auf einer einzigen Seite der Website, mit einer Oberfläche, die sich wie eine eigenständige Anwendung anfühlt und nicht wie ein WordPress-Bildschirm.

Das Rechnungs-Dashboard

Der Startbildschirm beantwortet die Frage, mit der jeder Unternehmer ein Rechnungstool öffnet: Wer schuldet uns was? Oben stehen vier Kennzahlen: berechnet, eingegangen, offen und überfällig. Jede wird für jede Währung getrennt berechnet, mit einem Umschalter, wenn ein Kontoinhaber in mehreren Währungen abrechnet. Darunter folgen die vier neuesten Rechnungen als Karten und danach die vollständige Rechnungsliste.

Die Liste lässt sich nach Rechnungsnummer oder Kundenname durchsuchen, nach Kunde, Status, Dokumenttyp und Zeitraum filtern und nach jeder Spalte sortieren. Aus jeder Zeile heraus können Sie eine Zahlung erfassen, die Rechnung als bezahlt markieren, das PDF herunterladen, sie duplizieren oder löschen, ohne sie zu öffnen.

Der Rechnungseditor

Der Editor ist wie das fertige Dokument aufgebaut. Was Sie eingeben, steht also dort, wo es später erscheint. Die Aktionen befinden sich in der rechten Spalte.

  • Vier Dokumenttypen: Invoice (Rechnung), Quote (Angebot), Proforma und Credit Note (Gutschrift).
  • Automatische Nummerierung mit einem Präfix pro Nutzer, etwa AT2623. Die Nummer bleibt bearbeitbar, Duplikate werden abgelehnt.
  • Rechnungs- und Fälligkeitsdatum. Das Fälligkeitsdatum ergibt sich aus dem Standard-Zahlungsziel der jeweiligen Person.
  • Positionen mit Menge, Einzelpreis, Beschreibung und einem Steuersatz aus der eigenen Liste des Nutzers.
  • Rabatt auf Rechnungsebene, eigene Felder wie eine Bestellnummer, zusätzliche Firmenangaben und eine freie Beschreibung.
  • Kundendaten, aus der Kundenkartei gewählt oder für einen Einzelfall eingetippt, mit der Option, den neuen Kunden direkt zu speichern.
  • Währungsauswahl pro Rechnung und Zahlungsbedingungen, die aus den Einstellungen vorbelegt werden.

Die Summen aktualisieren sich während der Eingabe. Wenn Sie ungespeicherte Änderungen verlassen wollen, fragt die App vorher nach. Dieses kleine Detail ist in einem Rechnungstool wichtiger als fast überall sonst.

Zahlungen, Status und „Als bezahlt markieren“

Niemand setzt den Status einer Rechnung von Hand. Er ergibt sich aus den erfassten Zahlungen und kann deshalb nie vom tatsächlichen Geldfluss abweichen.

Erfasste ZahlungenAngezeigter Status
KeineUnpaid (unbezahlt)
Weniger als die SummePartially paid (teilweise bezahlt)
Gleich oder mehr als die SummePaid (bezahlt)
Nicht vollständig bezahlt und Fälligkeit überschrittenOverdue (überfällig)
Dokumenttyp ist QuoteQuote (wird nie als Umsatz gezählt)

Jede Zahlung hat Datum, Betrag, Zahlungsart und eine optionale Notiz. So lassen sich Ratenzahlungen und Fehlbeträge durch Bankgebühren korrekt erfassen. Für den häufigsten Fall, dass der Kunde einfach bezahlt hat, gibt es den Button Mark as paid. Er erfasst mit einem Klick eine Zahlung über den Restbetrag mit dem heutigen Datum.

PDF-Export und Vorlagen

Jede Rechnung lässt sich in einer von drei Vorlagen ansehen und als A4-PDF herunterladen: dem schlichten Blank-Layout, dem Modern-Layout mit farbigem Kopfbereich und dem Classic-Layout mit Serifenschrift und Trennlinien.

Das PDF enthält:

  • Das Logo des Absenders und das Logo des Kunden. Beide lassen sich pro Rechnung ausblenden.
  • Beide Adressen.
  • Positionen, Rabatt, Steuer und Gesamtsumme.
  • Eingegangene Zahlungen, den offenen Betrag, die Bankverbindung und die Bedingungen.

Die Kundenkartei

Kunden werden einmal gespeichert und wiederverwendet. Zu jedem Kunden gibt es Logo, Firmen- und Ansprechpartnername, Adresse, Steuernummer und Notizen.

Die Kundenliste zeigt, was jeder Kunde noch schuldet, und die Seite eines Kunden zeigt:

  • Berechnete, eingegangene und offene Summen je Währung.
  • Die vollständige Rechnungshistorie.
  • Einen Button, der eine neue Rechnung mit bereits ausgefüllten Kundendaten startet.

Persönliche Einstellungen für jeden Kontoinhaber

Jeder Nutzer hat eigene:

  • Logo und die Wahl zwischen Einzelperson und Unternehmen.
  • Adresse und Telefonnummer mit internationaler Vorwahl.
  • Steuernummer und Website.
  • Standardwährung und Zahlungsziel in Tagen.
  • Bankverbindung, Rechnungspräfix und nächste Nummer.
  • Standardtext für Zahlungsbedingungen und eine Liste benannter Steuersätze.

Zwei Personen auf derselben Website können so Rechnungen ausstellen, die aussehen, als kämen sie von zwei verschiedenen Unternehmen, weil es genau so ist.

Registrierung, Freigaben und Admin-Bereich

Die App hat eigene Login- und Registrierungsbildschirme im Frontend. Kontoinhaber müssen wp-admin also nie sehen. Die öffentliche Registrierung ist optional. Ist sie aktiviert, können neue Konten eine Freigabe durch einen Administrator erfordern, und der Administrator erhält zu jeder Registrierung eine E-Mail.

In der App steht Administratoren ein Admin panel mit vier Bereichen zur Verfügung:

  • Overview: Anzahl der Konten und Rechnungsvolumen über alle Nutzer.
  • Users: Konten freigeben, sperren, reaktivieren, anlegen oder löschen und Rollen ändern.
  • Sign-up settings: Einstellungen zur Registrierung.
  • Messages: Nachrichten aus dem „Contact us“-Formular der App.
Übersicht im Admin-Bereich mit Kontenzahlen, Registrierungseinstellungen und Volumen je Währung
Die Admin-Übersicht: Konten, die auf Freigabe warten, Registrierungseinstellungen und Rechnungsvolumen über alle Konten.

Sie brauchen ein internes Tool, das zu Ihren Abläufen passt?

Rechnungen, Freigaben, Angebote, Kundenportale. Beschreiben Sie uns Ihren Workflow, und wir sagen Ihnen ehrlich, ob ein fertiges Plugin reicht oder sich eine Individualentwicklung lohnt.

Architektur: Wie ein WordPress Rechnungs-Plugin seine Daten speichern sollte

Die langfristige Qualität eines Plugins wird zum Großteil durch sein Datenmodell bestimmt. Es ist der eine Teil, den man nicht mehr leicht ändern kann, sobald echte Rechnungen existieren. Wir haben früh vier Entscheidungen getroffen, und alle vier haben sich bewährt.

Custom Post Types statt eigener Tabellen

Rechnungen, Kunden und Kontaktnachrichten sind private Custom Post Types. Jeder Datensatz gehört dem WordPress-Nutzer, der ihn angelegt hat, und die strukturierten Daten liegen in einem einzigen Post-Meta-Eintrag. Persönliche Einstellungen liegen in User Meta, pluginweite Optionen nutzen die Options API.

Eigene Datenbanktabellen wären bei sehr großen Datenmengen geringfügig schneller gewesen. Im Gegenzug bringen Post Types vieles kostenlos mit:

  • Übliche WordPress-Backups und -Migrationen enthalten die Daten automatisch.
  • Export-Werkzeuge verstehen sie bereits.
  • Der Objekt-Cache funktioniert ohne zusätzlichen Code.
  • Beim Löschen eines Nutzers können seine Datensätze ohne eine einzige Zeile Aufräumcode mit entfernt werden.

Ein Rechnungstool für ein Unternehmen enthält selten mehr als einige tausend Rechnungen pro Person. In dieser Größenordnung ist der native Ansatz der richtige.

Die Post Types sind vollständig privat registriert: nicht öffentlich, nicht abfragbar, von der Suche ausgeschlossen und vor REST API und Sitemaps verborgen. Eine Rechnung kann nicht versehentlich in den Suchergebnissen des Themes oder in der Sitemap eines SEO-Plugins landen.

Momentaufnahmen: Warum eine Rechnung Absender und Kunde kopiert

Eine Rechnung ist ein rechtlich relevanter Beleg eines bestimmten Zeitpunkts. Wenn Sie nächstes Jahr umziehen, müssen die Rechnungen des Vorjahres weiterhin die alte Adresse zeigen. Deshalb kopiert das Plugin beim Erstellen einer Rechnung die Absenderdaten in die Rechnung, und ebenso die Kundendaten.

Eine Änderung Ihrer Einstellungen oder der Adresse eines Kunden schreibt die Vergangenheit also nie um. Wenn ein alter Entwurf doch die neuen Daten übernehmen soll, bietet der Editor dafür eine bewusste Aktion, „Use my latest settings“, statt es stillschweigend zu tun.

Die Rechnung behält außerdem eine Verknüpfung zum Kundendatensatz, auf der die Salden je Kunde beruhen. Wird ein Kunde gelöscht, wird die Verknüpfung entfernt, die Momentaufnahme bleibt. Die Rechnung ist weiterhin korrekt lesbar und zählt nur nicht mehr zu einem Kunden, den es nicht mehr gibt.

Der Status wird berechnet, nie gespeichert

„Überfällig“ hängt vom heutigen Datum ab. Ein gespeicherter Status wäre also morgen schon falsch. Das Plugin speichert die Fakten: Positionen, Rabatt, Zahlungen und Fälligkeitsdatum. Den Status berechnet es bei jedem Lesen der Rechnung. Ein gespeichertes Statusfeld ist in Business-Software eine der häufigsten Ursachen für „laut Dashboard bezahlt, laut Bank nicht“.

Rechnen, das die Buchhaltung abnimmt

  • Der Rabatt wird vor der Steuer angewendet. Ein Rabatt von 10 % reduziert sowohl die Zwischensumme als auch die darauf berechnete Steuer, so wie es die meisten Steuersysteme vorsehen.
  • Steuer pro Position. Jede Position trägt ihren eigenen Satz, sodass eine Rechnung steuerpflichtige und steuerfreie Leistungen mischen kann.
  • Gutschriften zählen negativ in allen Summen, Angebote zählen gar nicht.
  • Währungen werden nie umgerechnet. Summen werden je Währung geführt. Eine stillschweigende Umrechnung zu irgendeinem Kurs ergäbe Zahlen, die weder zur Rechnung noch zum Kontoauszug passen.
  • Summen werden auf dem Server neu berechnet, und zwar aus den Positionen beim Speichern. Die Berechnung im Browser dient nur der Anzeige. Eine manipulierte Anfrage kann keine Summe speichern, die nicht aufgeht.

Eine REST API mit Eigentumsprüfung bei jeder Anfrage

Das Frontend kommuniziert mit WordPress über einen eigenen REST-Namespace. Jede Route durchläuft dieselbe Berechtigungsprüfung. Die Anfrage muss von einem angemeldeten Nutzer mit der Berechtigung des Plugins und einem aktiven Kontostatus stammen und eine gültige WordPress-Nonce mitführen.

Zusätzlich prüft jede Anfrage, die eine Rechnung oder einen Kunden betrifft, ob der Datensatz dem aktuellen Nutzer gehört. Falls nicht, antwortet die API mit not found statt forbidden. Das ist Absicht: „forbidden“ bestätigt, dass ein Datensatz mit dieser ID existiert, „not found“ verrät nichts. Wir testen das ausdrücklich, indem wir die Rechnung eines Kontos anfordern, während wir mit einem anderen angemeldet sind.

Jedes eingehende Feld wird bereinigt und in der Länge begrenzt:

  • Datumsangaben müssen einem strikten Format entsprechen.
  • Währungen müssen aus drei Buchstaben bestehen.
  • Dokumenttypen und Vorlagen müssen aus einer festen Liste stammen.
  • Logos werden nur als Bilder akzeptiert, die bereits in der eigenen Mediathek der Website liegen.

Hochgeladene Bilder werden dekodiert und darauf geprüft, ob es echte PNG-, JPEG-, GIF- oder WebP-Dateien sind, bevor sie in die Mediathek gelangen. SVG wird abgelehnt, weil eine SVG-Datei Skripte enthalten kann.

Ein praktisches Detail hat uns künftige Support-Anfragen erspart. Manche Shared-Hoster und Firewall-Regeln blockieren HTTP-PUT– und DELETE-Anfragen komplett. Die App sendet deshalb jeden Schreibvorgang als POST mit dem standardmäßigen Method-Override-Header von WordPress, den die REST API nativ unterstützt. Die Routen bleiben RESTful, und die Anfragen funktionieren auch bei restriktivem Hosting.

Konten, Rollen und Freigaben

Das Plugin fügt zwei Rollen und ein Berechtigungsmodell hinzu. Die WordPress-eigenen Rollen berührt es nur, um Administratoren Zugriff zu geben.

RolleDarf die App nutzenDarf Kontoinhaber verwaltenDarf Rechnungs-Admins und Rollen verwalten
AdministratorJaJaJa
Invoice Manager AdminJaJaNein
Invoice Account HolderJaNeinNein

Die mittlere Rolle gibt es, damit etwa die Büroleitung Nutzer freigeben und betreuen kann, ohne die Schlüssel zur gesamten Website zu erhalten. Administratoren können in der App nie gesperrt oder gelöscht werden, und niemand kann dort sein eigenes Konto löschen. Genau solche Fehler sperren Menschen aus ihrer eigenen Website aus.

Die öffentliche Registrierung ist deaktiviert, bis ein Administrator sie einschaltet. Dann ist das Formular vierfach geschützt:

  • Eine Nonce.
  • Ein verstecktes Honeypot-Feld, das Bots ausfüllen und Menschen nicht.
  • Ein Limit von fünf Registrierungen pro Netzwerkadresse und Stunde.
  • Eine Mindestlänge für Passwörter.

Mit aktivierter Freigabe kann sich ein neues Konto zwar anmelden, sieht aber nur den Hinweis „Warten auf Freigabe“, bis ein Administrator es freigibt. In diesem Moment erhält der Nutzer eine E-Mail. Das Sperren eines Nutzers meldet ihn sofort auf allen Geräten ab, indem seine WordPress-Sitzungen beendet werden, statt auf das Ablaufen eines Cookies zu warten.

Eine Vollbild-App, die das Theme nicht zerstören kann

Eine Rechnungs-App muss auf jeder Website, auf der sie installiert ist, gleich aussehen und sich gleich verhalten. Die Button-Stile eines Themes, die CSS-Resets eines Page Builders oder der Skript-Optimierer eines Caching-Plugins können eine anwendungsartige Oberfläche auf subtile Weise beschädigen. Deshalb übernimmt das Plugin die Darstellung seiner eigenen Seite vollständig.

Öffnet ein Besucher die App-Seite, liefert das Plugin statt des Themes sein eigenes, minimales Template aus. Dieses Template gibt nur das eigene Stylesheet und die eigenen Skripte des Plugins aus, über die Standardfunktionen von WordPress, und nichts vom Theme oder von anderen Plugins. Die Seite weist Caches außerdem an, sie nicht zu speichern, und Suchmaschinen, sie nicht zu indexieren, denn sie ist eine Anwendung und kein Inhalt.

Die Oberfläche selbst ist in einfachen JavaScript-Modulen ohne Framework geschrieben und zu einer einzigen lesbaren Datei gebündelt. Die Navigation nutzt Hash-Routen. Der Wechsel zwischen Rechnungen, Kunden und Einstellungen lädt die Seite also nie neu, und der Zurück-Button des Browsers funktioniert trotzdem. Die Schrift DM Sans ist im Plugin enthalten und wird nicht von einem Schriftendienst geladen. Die App stellt daher keinerlei Anfragen an Server von Drittanbietern.

Das Layout wurde von Anfang an für Smartphones konzipiert. Auf kleinen Bildschirmen:

  • Wird die Seitenleiste zum ausklappbaren Menü.
  • Werden Datentabellen zu gestapelten Karten, mit einer Beschriftung an jedem Wert.
  • Ordnet sich der Rechnungseditor einspaltig an.

Rechnungen werden oft vom Handy aus geprüft, wenn ein Kunde sagt, er habe bezahlt.

Rechnungs-Dashboard auf einem Smartphone
Das Dashboard auf dem Smartphone.
Rechnungsliste als gestapelte Karten auf einem Smartphone
Die Rechnungsliste wird zu gestapelten Karten, Mark paid bleibt nur einen Tipp entfernt.

PDF-Rechnungen direkt im Browser erzeugen

Serverseitige PDF-Erzeugung in PHP bedeutet meist schwere Bibliotheken, Schriften auf dem Server, Speichergrenzen und stark abweichende Ergebnisse je nach Hoster. Wir erzeugen das PDF stattdessen im Browser des Nutzers:

  1. Die Rechnung wird als HTML-Dokument im A4-Format dargestellt.
  2. Dieses Dokument wird in ein Bild umgewandelt.
  3. Das Bild wird mit der Open-Source-Bibliothek html2pdf.js in eine PDF-Datei eingefügt.

Das hat drei Vorteile:

  • Das PDF sieht exakt aus wie die Vorschau am Bildschirm, weil es die Vorschau ist.
  • Es funktioniert bei jedem Hoster.
  • Keine Rechnungsdaten werden zur Umwandlung irgendwohin gesendet.

Der Nachteil: Der Text im PDF ist ein Bild und kein markierbarer Text. Für Rechnungen, die gelesen, gedruckt und abgelegt werden, ist das ein akzeptabler Preis für überall identische Ergebnisse.

Die Fehler, die wir vor unseren Kunden gefunden haben

Jeder dieser Fehler war auf einem echten Bildschirm zu sehen. Sie lohnen eine Beschreibung, weil jeder für eine Fehlerklasse steht, die auch in anderen Projekten auftritt.

Die leere zweite Seite wegen eines halben Pixels

Einseitige Rechnungen wurden als zweiseitige PDFs heruntergeladen, und die zweite Seite war leer. Die Ursache: Das Dokument am Bildschirm hatte eine Mindesthöhe von 1123 Pixeln, damit die Vorschau wie ein ganzes Blatt Papier aussieht. A4 ist bei 96 DPI aber 1122,5 Pixel hoch. Dieser Überhang von einem halben Pixel genügte, damit die PDF-Bibliothek eine neue Seite begann.

Die Korrektur entfernt die Mindesthöhe nur während des Exports, die Vorschau sieht also weiterhin wie Papier aus. Bestätigt haben wir das durch Zählen der Seiten im erzeugten PDF: zwei vor der Korrektur, eine danach. Eine Rechnung mit 45 Positionen läuft weiterhin korrekt auf eine zweite Seite mit Inhalt über.

Ein Logout-Link, der sich selbst maskierte

Die WordPress-Funktion für die Logout-URL liefert eine bereits für HTML maskierte URL, in der die Kaufmanns-Und-Zeichen als & geschrieben sind. In einem HTML-Attribut ist das korrekt, in JavaScript falsch: Dort zerstörte das maskierte Zeichen das Sicherheitstoken und damit den Logout. Die Korrektur dekodiert die URL einmal, bevor sie an die App übergeben wird. Ein kleiner Fehler, aber typisch für die Grenze zwischen PHP-Templates und JavaScript.

Kundenlogos, die nie auf der Rechnung ankamen

Das Logo eines Kunden ließ sich hochladen und wurde korrekt gespeichert, erschien aber nie auf Rechnungen. Die Momentaufnahme, die in jede Rechnung kopiert wird, enthielt es schlicht nicht. Die Korrektur hatte zwei Teile:

  • Neue Rechnungen enthalten das Logo jetzt in der Momentaufnahme.
  • Früher gespeicherte Rechnungen greifen beim Lesen auf das aktuelle Logo des verknüpften Kunden zurück, ohne die gespeicherten Daten umzuschreiben.

Gespeicherte Daten unangetastet zu lassen, wenn man ein Darstellungsproblem behebt, ist eine Gewohnheit, die sich lohnt.

Eine Dashboard-Karte, die der Tabelle widersprach

Nachdem eine Rechnung in der Liste als bezahlt markiert wurde, wurde die Tabellenzeile grün, doch die Karte „Aktuelle Rechnungen“ darüber zeigte bis zum Neuladen weiterhin Unpaid. Zwei Ansichten derselben Daten waren aus dem Takt geraten. Jetzt stellt jede Aktion, die eine Rechnung ändert, den gesamten Bildschirm mit frischen Daten neu dar. So stimmen alle Zahlen auf der Seite immer überein.

Die Ausrichtung nach dem Hinzufügen eines Logos

Mit dem Kundenlogo über der Adresse begann der „To“-Block tiefer als der „From“-Block, und die Rechnung wirkte unausgewogen. Die Lösung war, das Logo rechts neben die Adresse zu setzen: Beide Blöcke beginnen auf derselben Zeile, und das Logo fluchtet mit der Rechnungsnummer darüber. Anschließend haben wir der Kundenspalte etwas mehr Breite gegeben, damit eine typische Schweizer Straßenadresse in eine Zeile passt. Die Lehre daraus: Testen Sie Rechnungslayouts mit echten Kundendaten, denn Platzhalternamen sind immer praktisch kurz.

Vorbereitung für das Plugin-Verzeichnis von WordPress.org

Code, der auf der eigenen Website funktioniert, und Code, der die Prüfung von WordPress.org besteht, sind nicht dasselbe. Das Verzeichnis hat eigene Regeln, und wir haben vor der Einreichung einiges angepasst, um sie zu erfüllen.

  • Keine Aufrufe externer Server. Die Schrift wurde ursprünglich von einem Schriftendienst geladen, wodurch die IP-Adresse jedes Besuchers an einen Dritten ging. Sie ist jetzt unter ihrer offenen Schriftlizenz im Plugin enthalten.
  • Skripte und Stile laufen über die WordPress-eigenen Funktionen. Fest eingetragene script- und link-Tags wurden durch registrierte, versionierte Assets ersetzt. Die Laufzeitkonfiguration wird über den Standardmechanismus für Inline-Skripte übergeben.
  • Lesbarer Quellcode. Das Verzeichnis akzeptiert keinen minifizierten Code ohne Quellen. Das App-Bundle wird unminifiziert ausgeliefert, die Originalmodule liegen bei, und die Readme erklärt, wie man es neu baut.
  • Lizenzen von Drittanbietern genannt. Die PDF-Bibliothek und die Schrift sind in der Readme mit Lizenz und Quelllink aufgeführt, die Lizenzdateien liegen dem Plugin bei.
  • Keine Core-Hooks durch das Plugin ausgelöst. Eine frühe Version löste nach der Registrierung die WordPress-eigene Login-Aktion aus. Heute protokolliert das Plugin den Login über eigenen Code.
  • Deinstallation nur mit Zustimmung. Das Löschen des Plugins entfernt nichts, solange der Administrator das Löschen der Daten nicht ausdrücklich verlangt hat. Rechnungen sind Geschäftsunterlagen, und sie durch einen versehentlichen Klick zu verlieren, ist nicht akzeptabel.
  • Eine vollständige Readme mit Kurzbeschreibung, Installationsschritten, FAQ, Datenschutzabschnitt und Changelog. Der Code ist so aufgebaut, dass das offizielle Plugin-Check-Tool ihn sauber prüfen kann.

Keine dieser Regeln hat das Plugin schlechter gemacht, einige haben es besser gemacht. Das Einbinden der Schrift etwa hat eine Datenschutzfrage vollständig aus der Welt geschafft.

Sie möchten ein sauber gebautes WordPress-Plugin, vom Datenmodell an?

Schicken Sie uns, was das Tool leisten soll. Innerhalb eines Werktags erhalten Sie einen klaren Umfang, die Abwägungen und einen Festpreis.

Individuelles WordPress Rechnungs-Plugin oder eine fertige Lösung?

Ehrlich gesagt sollten die meisten Unternehmen kein individuelles Rechnungstool in Auftrag geben. Wenn eine einzige Person ein paar Rechnungen im Monat in einer Währung schreibt, ist sie mit einem fertigen Produkt gut bedient, und das kostet weniger als jede Individualentwicklung. Eine Individualentwicklung wird zur besseren Option, wenn mehrere der folgenden Punkte zutreffen:

  • Mehrere Personen brauchen getrennte, voneinander isolierte Rechnungsstellung in einem System, und die Preise pro Nutzer werden spürbar.
  • Die Rechnungsstellung muss an etwas Unternehmensspezifisches angebunden werden, etwa ein Buchungssystem, eine Projektverwaltung, ein ERP oder ein Kundenportal.
  • Sie rechnen in mehreren Währungen ab und brauchen Summen, die nie hinter Ihrem Rücken umgerechnet werden.
  • Ihre Rechnungen brauchen Regeln, die Standard-Tools nicht abbilden, etwa eigene Freigabeschritte, Dokumenttypen oder Nummernkreise.
  • Die Finanzdaten sollen in einer Infrastruktur bleiben, die Ihnen gehört und die Sie selbst sichern und kontrollieren.

Trifft nur einer dieser Punkte zu, prüfen Sie zuerst genauer die fertigen Produkte. Treffen drei oder mehr zu, kostet ein fokussiertes Plugin wie dieses über zwei bis drei Jahre meist weniger als die Abos und Behelfslösungen, die es ersetzt. Und es tut genau das, was Sie brauchen.

Wie auch immer Sie sich entscheiden: Messen Sie jedes Rechnungstool an den Punkten, um die es in diesem Artikel ging:

  • Speichert es für jede Rechnung einen festen Stand, sodass spätere Änderungen an Ihren Daten oder denen eines Kunden alte Rechnungen nicht umschreiben?
  • Berechnet es den Status aus den Zahlungen, statt ihn zu speichern?
  • Hält es Währungen getrennt?
  • Trennt es Nutzer voneinander?
  • Kommen Sie jederzeit an Ihre Daten?

Häufige Fragen

Kann ein WordPress Rechnungs-Plugin mehrere Nutzer verwalten?

Ja, wenn es dafür gebaut ist. Im ArtinTech Invoice Manager gehört jede Rechnung und jeder Kunde dem Kontoinhaber, der sie angelegt hat, und die API prüft bei jeder Anfrage die Eigentümerschaft. Jeder Nutzer hat eigene Einstellungen, ein eigenes Logo, eine eigene Nummerierung und eigene Bankdaten und kann die Daten anderer nicht sehen.

Sendet das Plugin Rechnungsdaten an Dienste von Drittanbietern?

Nein. Alles wird in der eigenen WordPress-Datenbank der Website gespeichert. PDFs entstehen im Browser des Nutzers, und die Schrift ist im Plugin enthalten. Die einzigen ausgehenden Nachrichten sind normale WordPress-E-Mails, etwa Hinweise zu Registrierung und Freigabe.

Kann es Rechnungen in verschiedenen Währungen erstellen?

Ja. Jede Rechnung hat ihre eigene Währung, und Dashboard sowie Kundenseiten zeigen die Summen getrennt je Währung. Nichts wird umgerechnet, sodass die Zahlen immer zu den tatsächlich versendeten Rechnungen passen.

Funktioniert es mit meinem Theme oder Page Builder?

Ja. Die App-Seite wird mit dem eigenen Template und den eigenen Assets des Plugins dargestellt. Weder das Theme noch Elementor oder ein anderer Page Builder können ihr Aussehen oder Verhalten verändern. Der Rest Ihrer Website bleibt davon völlig unberührt.

Ist das Plugin auf WordPress.org verfügbar?

Wir haben es für das Plugin-Verzeichnis von WordPress.org vorbereitet, und es wird dort gelistet, sobald es die Prüfung bestanden hat. Wenn Sie es bis dahin nutzen möchten oder eine an Ihre Abläufe angepasste Version wünschen, nehmen Sie Kontakt mit uns auf.

Können Sie eine individuelle Version für mein Unternehmen bauen?

Ja. Eigene Rechnungslayouts, zusätzliche Dokumenttypen, die Anbindung an ein Buchungs- oder Projektsystem, Kundenportale und Freigabe-Workflows sind naheliegende Erweiterungen derselben Grundlage. Wie wir solche Projekte zuschneiden, lesen Sie bei unserer WordPress-Plugin-Entwicklung.

WordPress-Werkzeuge wie dieses zu bauen, ist ein Kernbestandteil unserer Arbeit. Manches sind kleine Korrekturen, etwa der cachebedingte 403-Fehler, den wir auf die Lebensdauer einer Nonce zurückgeführt haben. Anderes sind vollständige Anwendungen wie diese, umgesetzt im Rahmen unserer WordPress-Entwicklung und unserer individuellen CMS- und ERP-Entwicklung. Wenn Sie gerade ein Rechnungstool abwägen oder eine andere Software, um die Ihr Unternehmen ständig herumarbeiten muss, sprechen Sie uns an. Sie bekommen eine ehrliche Einschätzung, auch dann, wenn die Antwort lautet, dass ein fertiges Produkt genügt.

Share this article

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert