Verkaufsbeleg — Positionen (Sub-Route)
Zweck
Sub-Route /sales-documents/:id/items ist die Pflege-Sicht der Positionen eines Verkaufsbelegs. Anders als die globale Cross-Beleg-Sicht /sales-document-items (read-only Auswertung) erlaubt diese Sub-Route Hinzufuegen, Ändern und Löschen von Positionen am konkreten Beleg.
Voraussetzungen
Berechtigungen (CASL)
| Action | Subject | Wirkung | Keycloak-Rolle |
|---|---|---|---|
view | FE_SalesDocument, SalesDocument | Detail aufrufbar | — |
view/create/update/delete | SalesDocumentItem | Positionen pflegen | APP_SPEAMCORE_VIEW/CREATE/UPDATE/DELETE_SALES_DOCUMENT_ITEM |
view | Product | Produkt-Auswahl | APP_SPEAMCORE_VIEW_PRODUCT |
Schritt-für-Schritt-Anleitung
- Verkaufsbeleg (
/sales-documents/:id) → Tab Positionen. - + Position → Produkt wählen oder freie Position eintragen (Titel, Beschreibung, Menge, Preis, Einheit).
- Optional
optional/alternativemarkieren — wirkt sich auf Beleg-Summen-Berechnung aus. - Position in der Liste neu sortieren per Drag-and-Drop.

Positionen-Toolbar (6 Icons)
Direkt über dem Positionen-DataGrid sitzt eine kleine Icon-Reihe mit sechs Aktionen — sie sind das Herzstück der Positionen-Bearbeitung und in der Praxis täglich verwendet:
Icon: „➕ Position hinzufügen"
Klick öffnet ein Dropdown mit vier Position-Typen:
| Position-Typ | Bedeutung | Daten-Quelle |
|---|---|---|
| Produkt | Standard-Position aus dem Produkt-Stamm. | productId referenziert ein bestehendes Produkt; Snapshot-Felder (Titel, Beschreibung, Verkaufspreis, Einheit) werden bei Anlage befüllt. |
| Produkt (Kalkulation) | Wie „Produkt", zusätzlich mit ausführlicher Kalkulations-Aufschlüsselung im PDF. | productId + Kalkulations-Detail-Felder. |
| Produkt (benutzerdefiniert) | Produkt aus Stamm gewählt, aber Snapshot-Felder dürfen abweichend überschrieben werden — Stamm bleibt unverändert. | productId + customTitle/customDescription/customPrice. |
| Leere Text Position | Reine Text-Position ohne Produktbezug — z. B. Kapitel-Überschriften, Zwischentexte, Hinweise. | Nur title/description, kein productId. |
Icon: „📤 GAEB-Datei hochladen"
Klick öffnet einen Datei-Upload-Dialog. GAEB (Gemeinsamer Ausschuss Elektronik im Bauwesen) ist der deutsche Standard für elektronische Leistungsverzeichnisse im Bauwesen — Format *.x83, *.x84, *.x86, *.x89 (XML-basiert).
Hochgeladene GAEB-Dateien werden geparst, die Leistungspositionen werden 1:1 als SalesDocumentItem angelegt (mit Position, Titel, Beschreibung, Menge, Einheit, Preis). Erforderlich für Auftraggeber im Bauwesen die LV-Templates senden.
Format-Mapping:
<HierarchicalGroup>→ Kapitel-Position (Text-Position).<Item>→ Standard-Produkt-Position.<Pricing>→priceNetund ggf. Kalkulations-Komponenten.
Icon: „1. 2. 3. Pos.-Nr. neu nummerieren"
Klick durchnummeriert alle bestehenden Positionen neu — position-Feld wird auf 1, 2, 3, ... gesetzt, basierend auf der aktuellen Sortier-Reihenfolge der Liste (Drag-and-Drop).
Anwendungsfall: Nachdem Positionen umsortiert oder gelöscht wurden, sind die Positionsnummern unregelmäßig (z. B. 1, 3, 5, 8). Dieser Klick macht daraus wieder 1, 2, 3, 4.
Wirkung: PATCH /api/sales-document-items/:id für jede Position mit dem neuen position-Wert. Das ändert nichts am inhaltlichen Beleg, aber Anwender und Endkunde sehen saubere Nummerierung im PDF.
Icon: „↻ Produktdaten aktualisieren"
Klick synchronisiert die Snapshot-Felder aller Positionen mit dem aktuellen Produkt-Stamm.
Anwendungsfall: Ein Produkt wurde im Stamm geändert (z. B. neuer Verkaufspreis nach Listenpreis-Update), und der bestehende Beleg-Entwurf soll diese Änderung übernehmen.
Wirkung: Pro Position mit productId !== null: liest aktuelle Stamm-Werte → setzt priceNet, taxRate, unitId, ggf. title/description (je nach Typ — bei „benutzerdefiniert" bleiben Custom-Werte erhalten).
Icon: „📦 Vorlage speichern"
Klick öffnet ein Dialog zur Vorlagen-Erstellung. Die aktuellen Positionen des Belegs werden als wiederverwendbare Vorlage gespeichert — z. B. „Standard-Wartung Sprinkler 4x jährlich".
Felder im Dialog:
templateName(Pflicht) — Eindeutiger Name der Vorlage.templateDescription(optional) — Beschreibung was die Vorlage enthält.isPublic(Toggle) — Vorlage für alle Mitarbeiter sichtbar (defaultfalse= privat).
Wirkung: Erzeugt einen SalesDocumentItemTemplate-Datensatz. Spätere Wiederverwendung über das Icon „Vorlage laden".
Icon: „📋 Vorlage laden"
Klick öffnet einen Vorlagen-Auswahl-Dialog. Der Anwender wählt eine bestehende Vorlage; alle Positionen der Vorlage werden zusätzlich zum aktuellen Beleg hinzugefügt (nicht ersetzt — bestehende Positionen bleiben).
Anwendungsfall: Wartungsangebot mit immer-gleichen Standard-Leistungen schnell anlegen, dann individuell ergänzen.
Hinweis: Der productId der geladenen Positionen wird übernommen — aktuelle Stamm-Werte werden nicht zwingend nachgezogen. Empfehlung: nach „Vorlage laden" den Button „↻ Produktdaten aktualisieren" klicken.
Bulk-Auswahl in der Liste
Die erste Spalte des Positionen-DataGrids ist „Ausgewählt" mit einer Checkbox. Bei Mehrfach-Auswahl erscheint im Header eine Bulk-Aktions-Toolbar:
- Massen-Löschen — alle markierten Positionen entfernen.
- Massen-Verschieben — Positionen in einen anderen Beleg übernehmen.
- Massen-Aktualisieren — Produktdaten aller markierten Positionen synchronisieren.
Felder und Eingaben
| Feldname | Pflicht | Datentyp | Wirkung beim Ausfuellen | Voraussetzung |
|---|---|---|---|---|
productId | nein | UUID | Verweist auf Produkt — falls gesetzt, werden Snapshot-Felder vorbefuellt. | view:Product. |
position | nein | String | Positionsnummer (z. B. 1, 1.1). Auto-vergebene Reihenfolge. | — |
quantity | ja | Decimal | Menge. | — |
price | ja | Decimal | Verkaufspreis (netto). | — |
productTitle, productDescription | nein | String/TEXT | Anzeige-Texte (Snapshot vom Produkt oder freier Text). | — |
optional | nein | Boolean | Position als optional markieren. | — |
alternative | nein | Boolean | Position als Alternative markieren. | — |
accountId | nein | UUID | Buchhaltungskonto für Erloesbuchung. | — |
Wiederverwendbare Konzepte
Verknuepfungen zu anderen Modulen
- Verkaufsbelege — Eltern-Modul.
- Sales-Document-Items — globale Cross-Beleg-Sicht.
- Produkte — Snapshot-Quelle.
- Konten — Erloesbuchung.
API/Schnittstellen
| Methode | Endpoint | Zweck | CASL |
|---|---|---|---|
GET | /api/sales-document-items?filter[salesDocumentId] | Liste | view SalesDocumentItem |
POST | /api/sales-document-items | Anlegen | create SalesDocumentItem |
PATCH | /api/sales-document-items/:id | Ändern | update SalesDocumentItem |
DELETE | /api/sales-document-items/:id | Soft-Delete | delete SalesDocumentItem |
Versionshinweise
- 2026-04-30: Initiale Veroeffentlichung.