Key: faktura · Enthalten im Abo: Basis · Seit: v0.19.0–v0.19.4 (Juli 2026) · App: apps/faktura (Tabellen-Prefix faktura_)
Rechnungen mit normkonformer Swiss-QR-Rechnung: manuell (einzeln oder Massenlauf), automatisch (Automationen), mit Sammel-Freigabe, Zahlungserfassung und Mahnwesen. Konzept mit allen User-Entscheiden: docs/konzept-faktura.md.
Sidebar-Eintrag „Rechnungen" (nach Aktivierung), Tabs: Übersicht · Neue Rechnung · Automationen · Stammdaten. Alle Views hart Owner/Admin-only + Addon-Gate (Ausnahme vom „kein View-Gate"-Grundsatz — Finanzdaten).
Mehrere Rechnungsabsender (BillingProfile) pro Verein, einer Standard: Bankverbindung (seit v0.27.4 ein eigenes Vereins-Objekt mit IBAN, optionaler QR-IBAN und Kontoinhaber — dieselbe Bankverbindung nutzen Finanzkonto, Kontoauszug-Import und Zahlungsdatei; mit QR-IBAN erhalten Rechnungen QRR-Referenzen, sonst SCOR), Absenderadresse, Logo-Upload, MwSt-Nr./Satz (optional — Beträge gelten inkl.), Zahlungsfrist (Default 30 Tage), Textbausteine (Rechnungs-Einleitung/Fusszeile, Versand-Mail-Betreff/-Text mit Platzhaltern {name} {nummer} {betrag} {frist}). IBAN-Eingabe mit/ohne Leerzeichen, wird normalisiert und per mod97 validiert; nur CH/LI.
{jahr}-{seq4} pro Verein lückenlos (select_for_update); kein Löschen — nur Storno (Nummernkreis bleibt intakt).kaw-sponsoring v4.22.2).qrcode-Package, QR als Inline-SVG mit Schweizerkreuz). Auslieferung nur über Admin-geprüfte View.entwurf → versendet → bezahlt | storniert.„Neue Rechnung" → Umschalter „Mehrere (Massenlauf)":
receives_invoice), sonst Hauptperson, sonst erster aktiver Link (resolve_billing_person; bis v0.28.126 Canvas-Rolle billing → is_primary → Hauptkontakt). Firmen: Adress-Rolle billing → main → einzige Adresse. Gruppen lösen Person-/Member-/Firmen-Einträge auf.notes («Anna Muster erhält 2 Rechnungen, eine je Mitgliedschaft»). Limit 500/Lauf.Checkboxen an Entwürfen: „📬 Zustellen (✉️ n · 🖨 m)" (seit v0.27.1: ein Klick schickt die Mails an alle mit E-Mail-Adresse und markiert die übrigen als Brief; das Ergebnis bietet das Sammel-PDF für die Brief-Empfänger zum Download — jede Entwurfszeile zeigt vorher ✉️ oder 📄), dazu weiterhin „Nur E-Mail", „Brief-PDF" (EIN Sammel-PDF, eine Seite pro Rechnung) und „Als versendet (Brief) markieren". Limit 200 pro Freigabe, Bestätigungs-Dialog (SMTP ist echt). Der Pre-Flight des Massenlaufs zeigt die Aufteilung E-Mail/Brief bereits vor dem Erstellen.
manage.py run_invoice_automations, Host-Cron täglich 05:15 (crontab yves, Log /srv/cluhu/compose/faktura_automations.log) — die erste Cron-Infrastruktur des Projekts.source='ausbuchung'). Zahlungen löschbar, Status wird zurückgerechnet.Was kann es (aus User-Sicht): Unter Stammdaten gibt es einen Artikelstamm: «Mitgliederbeitrag Aktiv 150», «Mitgliederbeitrag Junior 80», «Instrumentenmiete 50» — je mit Preis, Ertragskonto und Kostenstelle. Im Massenlauf und in Automationen ist jede Position ein Satz «Wenn …, dann …»: Position aus Artikel oder manuell, Menge fix oder aus einer Zahlenspalte, Betrag aus Spalte (z.B. «Beitrag individuell»), Rabatt in Prozent oder Franken auf eine Position oder auf alle. Bedingungen: Custom-Spalte (Dropdown-Optionen als Auswahl), Status aktiv/passiv, «ist in Gruppe», Alter am Stichtag. Ohne Bedingung gilt die Zeile immer; mehrere Bedingungen müssen alle zutreffen. So entsteht aus EINER Automation «Jahresrechnung» für jedes Mitglied die passende Rechnung: Beitrag nach Kategorie, Miete wenn Miete=ja, Familienrabatt wenn in Gruppe Familie.
Prüfen vor dem Lauf: «Empfänger prüfen» zeigt pro Person die Positionen und das Total (Zeile aufklappen), die Trefferzahl jeder Regel (0 Treffer = Warnung), Empfänger ohne Position und die Summe. Bei Automationen macht «Simulation» dasselbe, ohne Entwürfe zu erzeugen; «Entwürfe erzeugen» ist der frühere Testlauf. Duplizieren legt eine pausierte Kopie an (Juli aus Januar).
Buchhaltung: Beim Versand bucht die Soll-Stellung je Position auf das Ertragskonto des Artikels (Kostenstelle inklusive), Rabatte im Soll auf 3800 Ertragsminderungen. Die Rechnung zeigt im Detail das Konto je Position.
Warum so gebaut: Kategorie, Miete und Instrument sind beim Verein ohnehin Custom-Spalten (oft aus dem Import), ein zweites «Kategorie»-Feld wäre redundant. Die Preislogik liegt an einem Ort statt an 300 Mitgliedern; Alters-Regeln pflegen sich selbst, eine von Hand gesetzte Kategorie «Junior» veraltet. Verweise werden per ID gespeichert, Umbenennen bricht nichts; gelöschte Spalten oder Artikel erscheinen als Warnung an der Automation. Keine Verschachtelung und kein Sonst-Zweig, damit Vorstandsmitglieder die Regeln lesen können. Rabatte als eigene Minus-Zeile, damit der Revisor den Bruttoertrag sieht. Simulation, weil Entwürfe nicht nachbearbeitet, nur storniert werden können.
Bewusst nicht gebaut: Familienmitgliedschaft mit Position pro Kind (später), Vorschau am Mitglied, Ertragskonto an manuellen Positionen (sie erben das Konto der Automation).
Vereine mit nur dem Rechnungs-Addon lesen den Kontoauszug (camt.053/054) direkt in der Übersicht ein («🏦 Kontoauszug einlesen»): Gutschriften mit QR- oder SCOR-Referenz werden als Zahlung der passenden offenen Rechnung erfasst (auch Teil- und Überzahlungen), alles ohne Referenz wird aufgelistet und bleibt manuell, Belastungen werden ignoriert. Ein zweites Einlesen derselben Datei erkennt die bereits erfassten Zahlungen. Mit aktiver Buchhaltung läuft der Abgleich ausschliesslich im Matching-Center — dort entstehen auch die Buchungen.
Warum so: Ein Live-Abgleich per EBICS (Bankvertrag für Geschäftskunden) oder bLink (SIX-Onboarding) lohnt sich für Vereine nicht; der tägliche camt-Download aus dem E-Banking ist der realistische Weg. Nur Referenz-Treffer werden automatisch erfasst — bei Vereinsgeld ist ein falsch zugeordneter Betragstreffer teurer als eine manuelle Erfassung.
Unter Rechnungen › Stammdaten und in Buchhaltung › Einstellungen › Konten steht dieselbe Karte Bankverbindungen: Bezeichnung, Kontoinhaber, IBAN, QR-IBAN. Der Rechnungsabsender wählt eine Bankverbindung, das Finanzkonto der Buchhaltung ebenso; ohne explizite Wahl verknüpft sich der Absender automatisch mit dem Finanzkonto derselben Bankverbindung. Eine Bankverbindung lässt sich nur löschen, wenn nichts mehr darauf zeigt, die Meldung nennt die Verwender. Bestehende IBANs wurden beim Update automatisch zu Bankverbindungen.
Warum so: Vorher lag die IBAN am Absender und am Finanzkonto, zusammengehalten durch Kopie und Hinweis. Mit einem Objekt gibt es eine Wahrheit, mit und ohne Buchhaltung, und die Zahlungsdatei für Auszahlungen hat einen Absender mit Kontoinhaber. «Konto» heisst in den Rechnungen jetzt «Rechnungsabsender», damit der Begriff Konto der Buchhaltung gehört.
Wer in der Mitglieder- oder Personenliste das Detail öffnet, sieht unten den Block Rechnungen: die bisherigen Rechnungen mit Status, offenem Betrag und Mahnstufe, dazu «Nächste Rechnungen laut Automationen» — je aktive Automation, die auf diesen Eintrag zutrifft, den nächsten Termin, die Positionen gemäss Regeln (Rabatte grün) und das Total, mit Hinweis «bereits fakturiert» oder «keine Position». So lässt sich vor dem Januar-Lauf pro Mitglied prüfen, was kommt, ohne die Simulation der ganzen Automation zu öffnen.
Warum so: Die Regeln liegen an der Automation; die Vorschau am Mitglied ist der Gegenpol dazu und ersetzt, was eine Beitragskategorie am Mitglied gezeigt hätte. Sie rechnet live mit denselben Regeln, es gibt also keinen zweiten Stand. Bewusst nicht im Portal: Mitglieder sehen Beiträge erst, wenn der Verein die Rechnung verschickt.
Mit aktiver Buchhaltung zeigt das Rechnungs-Detail den Block «Buchhaltung»: Soll-Stellung, Zahlungen, Ausbuchungen und Stornos mit Buchungsnummer und Sprung ins Journal; umgekehrt verlinkt das Journal auf PDF und Rechnung. Details auf der Buchhaltungs-Seite.
Familienfall (Position pro verknüpfter Person); Event-Rechnungen (Kalender-Anbindung); Kassier-Rolle.
qrcode-Package ist in requirements.txt UND im laufenden Container nachinstalliert — beim Image-Rebuild automatisch dabei.floatformat lokalisiert mit Komma (de-ch) — alle PDF-Beträge werden serverseitig CH-formatiert (Punkt, Tausender-Apostroph).{# #}-Kommentare sind nicht mehrzeilig — ein mehrzeiliger Kommentar im Seiten-Template leakte bis v0.19.4 als sichtbare Leerseite in jedes PDF.Mit dem Buchhaltungs-Addon (drei Integrationsregeln, Soll-Stellung, Matching-Center):
YYYY-MM, Trigger-Tag 29–31 → Monatsletzter, Idempotenz pro Monat)./api/faktura/invoices/by-reference/ → öffnet direkt den Zahlungs-Dialog der gefundenen Rechnung (für Zahlungserfassung ohne camt)./api/buchhaltung/finance-accounts/ liefert sonst active:false).apps/buchhaltung/integration.py (idempotent, defensiv — Faktura bricht nie ab; ohne aktives Buchhaltungs-Addon No-Op).Rechnungen-Seite › Aktionen › Export Rechnungen (Liste plus Blatt «Zahlungen», Filter Status/Jahr/Suche) und Export Artikel, als Excel oder CSV; dieselben Listen auch unter Buchhaltung › Einstellungen › Export. Details: Listen-Export.
Rechnungen aus dem Addon Inventar (v0.28.3): Bei der Rückgabe einer vermieteten Ausleihe entsteht ein Rechnungsentwurf (Miete, Nachbelastung) an die ausleihende Person; Versand, Mahnwesen und Zahlungsabgleich laufen wie bei jeder Rechnung. Siehe Addon: Inventar.
Was kann es: Zahlt jemand mehr als den offenen Betrag, fragt CluHu nach. Bei «Zahlung erfassen» und im Zahlungsabgleich (Bestätigen und Zuweisen) öffnet sich das Popup «Überzahlung von CHF x»: Auswahl des Ertragskontos, Vorgabe ist das Konto der Rechnung («wie die Rechnung», aus Automation, Absender oder Standard), «Abbrechen» bricht die Zahlung ab. Gebucht wird der Anteil bis zum offenen Rest auf Forderungen, der Mehrbetrag auf das gewählte Konto mit der Kostenstelle der Rechnung; der Buchungstext nennt «(Überzahlung CHF x auf Konto)». «Alle bestätigen» nimmt die Vorgabe. Ohne Überzahlung ändert sich nichts.
Warum so: Vorher ging die ganze Zahlung «Bank an Forderungen», die Rechnung stand im Minus und der Kassier buchte von Hand um. Auslöser waren die echten Daten des Musikvereins Spiez: Passivmitglieder, die 25 bis 100 statt 20 Franken zahlen. Nicht vollautomatisch, weil nur der Kassier weiss, ob der Mehrbetrag Spende, freiwilliger Mehrbeitrag oder Irrtum ist; die Vorgabe macht den Normalfall zu einem Klick.
Nicht gebaut (Stand v0.28.42): Rückzahlung oder Gutschrift auf die nächste Rechnung.
Problem: Ein Tester meldete «Rechnungen nur über das Addon erreichbar». Seit v0.26.14 gilt Rechnungen als aktiv, sobald die Buchhaltung aktiv ist, ohne eigenen Addon-Eintrag. Register und Kennzahlen-Block prüften aber noch auf diesen Eintrag und fehlten bei jedem Mandanten, der Rechnungen nur über die Buchhaltung nutzt.
Lösung: Die Prüfung nutzt die bündelbewusste Abfrage addon_is_active() aus apps/core/addon_state.py. Lehre: Aktiv-Status nur über die zentrale Abfrage. Jede eigene Query ist der nächste Bündel-Fehler.
Was kann es: Die Rechnungsperson einer Mitgliedschaft ist, wer im Register Mitglied-Empfänger das Rechnungs-Radio trägt (auch ohne E-Mail, dann Brief); Rollencodes zählen nicht mehr. Zwei Geschwister in getrennten Mitgliedschaften mit derselben Mutter ergeben zwei Rechnungen, das Protokoll des Laufs (AutomationRun.notes, auch in «Empfänger prüfen» und «Simulation») nennt es; die Sammelrechnung je Zahler folgt in Etappe 4 (P22), ebenso der Geschwisterrabatt (P23). «Positionen je Person» zählt nur Personen mit Haken «macht mit» (Eltern bekommen keine Positionen). Neue Bedingung «Alter der Teilnehmenden» neben «Alter» (das Alter der Zahlperson): rechnet mit der teilnehmenden Person, bei mehreren mit der jüngsten. Beendete Links (Austritt) und archivierte Mitgliedschaften werden nicht fakturiert.
Assistent «Beitragscode» im Automations-Editor (Knopf in der Positionen-Leiste bei Quelle Mitglieder): Auswahlspalte der Mitgliedschaft wählen («Beitragscode»), Tabelle Option × Anzahl Mitgliedschaften × Artikel (wählen, «kein Artikel, keine Rechnung» oder «Artikel anlegen …») × Preis, Schalter «Betrag statt Artikelpreis aus Zahlenspalte», Knopf «n Zeilen erzeugen». Das Ergebnis sind gewöhnliche Automationszeilen (Artikel + Bedingung «Spalte ist Option»), kein neues Modell; Codes ohne Artikel erscheinen als Lücke unter Mitglieder › Import nachbearbeiten («übersprungen», nie eine leere Rechnung). Die Automationen-Liste zeigt «gesteuert von Beitragscode». API GET/POST /api/faktura/beitragscode/….
Zustellung (invoice_recipients): die Rechnungsmail geht an die Personen, die der Haushaltsindex für den Bereich «Rechnung» liefert, sonst an den Schuldner; damit haben Rechnungs-Radio und «sieht Rechnungen» im Mitgliederportal (geplant) dieselbe Quelle.
Warum so: Die Dedupe-Lücke war die Pflichtkorrektur vor jedem Eltern-Kind-Verein; in Form E ändert sich nichts. Der Beitragscode bleibt ein Auswahlfeld an der Mitgliedschaft (der Import legt es an), die Deutung gehört der Faktura. Die Faktura hatte bis dahin keine Tests; apps/faktura/tests_etappe2.py (30 Tests) hielt zuerst den alten Stand fest. Das Spalten-Flag «für Rechnungen nutzbar» wird von der Spalten-API nicht mehr gesetzt (war nie gelesen).
Was kann es: Schalter «Eine Rechnung je Zahlperson (Geschwister zusammenfassen)» am Massenlauf und an der Automation (collect_by_payer, Vorgabe aus = eine Rechnung je Mitgliedschaft wie seit v0.28.127). Eingeschaltet werden Mitgliedschaften mit derselben Rechnungsperson eine Rechnung; jede Position trägt den Namen der Teilnehmenden («Jahresbeitrag Jugend — Lea Muster»), Rabatte bleiben der Mitgliedschaft zugeordnet, die Rechnung kennt alle enthaltenen Mitgliedschaften (Invoice.members), die Idempotenz prüft je Mitgliedschaft und Periode, das Protokoll nennt «Anna Muster: eine Sammelrechnung für Lea Muster und Tim Muster», das Detail-Panel beider Kinder zeigt dieselbe Rechnung. Neue Bedingung «Geschwister (n-tes Kind)» (sibling_rank, ab dem 2. bis 6. Kind): Rang der Teilnehmenden unter allen Mitgliedschaften mit derselben Rechnungsperson oder gemeinsamen Betreuenden, nach Geburtsdatum (älteste zuerst; ohne Geburtsdatum Anlage-Reihenfolge); mit einer Rabattzeile ergibt das den Geschwisterrabatt. Form E hat immer Rang 1. Migration faktura 0012.
Warum so: Zwei Rechnungen je Zahlperson waren die Pflichtkorrektur der Etappe 2; die Sammelrechnung ist der Komfort darauf, bewusst als Schalter, damit Bestandsvereine nichts ändern müssen. Der Rang zählt über Betreuende, nicht nur über die Rechnungsperson, weil getrennt lebende Eltern die Rechnung aufteilen können.