Rechnung speichern — Ablauf und Regeln

Die Schritte beim Anlegen und Ändern einer Rechnung: Kontingent, Validierung, Dublettenprüfung, Belegblock-Sperre, gemeinsamer Einfügeweg, Rücklesen und Berechtigungen.

Das Speichern einer Rechnung läuft über einen Endpunkt (finance/invoice.save); die invoice_id entscheidet zwischen Anlage und Änderung. Jede Anlage nutzt den gemeinsamen Weg addInvoice().

Datenmodell

Die Tabellennamen tragen in der Datenbank das eigene Präfix der Installation.

TabelleRolle
invoice, invoice_itemKopf und Positionen (schreibt Dlbtinvoice::add())
invoice_retentionEinbehaltszeilen (saveRetentions())
Belegblock-Tabellenüber das Modell masterdata/invoice_block, mit Nummernsperre
allocation, label_linkAnalytik und Labels (bei Änderung)

Ablauf der Anlage

  1. Recht: canSave(route, 0) — fehlt der Schlüssel add im Funktionsstamm, entscheidet edit; der Eigentümer (company_client_id) muss im Bereich liegen (ownerInScope).
  2. Kontingent: dlbtquota->checkAction(user, route, 'add', 1); die Zustände need_credit / need_plan führen zu einem Fehler (error_quota_*).
  3. Feldvalidierung, Dublettensuche (findDuplicateInvoice; eigene Meldung für eine Dublette im Papierkorb), bei Storno-/Korrekturrechnungen ist die referenzierte Rechnung Pflicht und muss existieren, Aufrechnungsprüfung (checkOffsetInvoice), Einbehaltsgrenze.
  4. Bei eigener nummerierter Ausgangsrechnung: Sperre des Nummernkreises (lockSeries), Nummernbildung, Prüfung der Datumsreihenfolge.
  5. addInvoice($post), danach Rücklesen (getInvoice); fehlt die Rechnung: error_not_created, die Nummer wird nicht verbraucht.
  6. commitSeriesSeq, Rechnungstyp setzen (applyKind()), Kontingent verbrauchen (consumeAction()), Einbehalte speichern, Protokoll.
  7. Die Antwort liefert die neue invoice_id; es gibt keine Weiterleitung.

Änderung

Gleiche Validierung; ist die Rechnung nummeriert/abgeschlossen (getSeriesLock()['numbered']), folgt error_invoice_finalized. Sonst editInvoice($id, $post): vollständiger Austausch von Kopf und Positionen, Neuberechnung in der Bibliothek, applyKind(), Einbehalte, Protokoll. Auch das Öffnen des Formulars prüft canSave und ownerInScope: die Rechnung eines fremden Unternehmens lässt sich nicht öffnen.

Fehlerschlüssel

error_supplier, error_customer_required, error_currency, error_date, error_invoice_no_form, error_number_in_own_series, error_duplicate, error_duplicate_trashed, error_offset_*, error_retention_over, error_reference_*, error_number_client, error_number_busy, error_number_block, error_series_prefix_taken, error_number_date_order, error_quota_*.

Formularhilfen

  • getDueDate, getTaxData, getRate — Fälligkeit, MwSt.-Satz, MNB-Kurs; Recht: add oder edit.
  • offsetinvoices — aufrechenbare Ausgangsrechnungen; Recht: edit + Eigentümerbereich.
  • docsearch, attachdocument, detachdocument, unlinkdocument — Dokument der Dokumentenzentrale suchen, mit der Rechnung verknüpfen oder lösen, alte invoice_document-Verknüpfung auflösen; Recht: edit + Bereich.
  • Die PDF-Felder (Vorlage, Klausel, Hinweis) hängen am Recht pdf.

Berechtigungen

  • Ebene 1: Grundzugriff und Änderungsrecht auf dem Rechnungspfad.
  • Ebene 2: add (im Funktionsstamm nicht eingestuft, nur in den Abhängigkeitstabellen), edit (BASE).
  • Ebene 3: ownerInScope und invoiceInScope.