Standorte
Zweck
Standorte (Niederlassungen) gehören zu genau einem Kunden und tragen die operativen Datensaetze: Anlagen (Brandmeldesysteme etc.), Aufträge, Verkaufsbelege, Kontakte und Sonderkonditionen. Sie sind die feinste Verortungs-Ebene und werden in Belegen als parentType = 'Location' referenziert.
Voraussetzungen
Berechtigungen (CASL)
Frontend-Page-Guard:
| Action | Subject | Wirkung | Keycloak-Rolle |
|---|---|---|---|
view | FE_Location | Standortliste und -details aufrufbar | — |
view | Location | Daten lesbar | APP_SPEAMCORE_VIEW_LOCATION |
view | Customer | Parent-Kunde sichtbar | APP_SPEAMCORE_VIEW_CUSTOMER |
API-Datenzugriff:
| Action | Subject | Endpoint | Keycloak-Rolle |
|---|---|---|---|
view | Location | GET /api/locations, GET /api/locations/:id | APP_SPEAMCORE_VIEW_LOCATION |
create | Location | POST /api/locations | APP_SPEAMCORE_CREATE_LOCATION |
update | Location | PATCH /api/locations/:id | APP_SPEAMCORE_UPDATE_LOCATION |
delete | Location | DELETE /api/locations/:id | APP_SPEAMCORE_DELETE_LOCATION |
GET-Antworten werden serverseitig 300 s gecacht, Mutationen invalidieren den Cache.
Schritt-für-Schritt-Anleitung
Standort anlegen
- Öffnen Sie den Kunden, dem der Standort gehören soll.
- Wechseln Sie in den Tab Standorte (
/customers/:customerId/locations). - Klicken Sie + Neu.
- Pflegen Sie Name und ggf. Adresse / Geokoordinaten.
- Speichern.
locationNowird automatisch generiert (fortlaufend pro Kunde).
Standort wechselnden Kunden zuordnen
Nicht möglich. customerId ist nach Anlage disabled, um Belege und Anlagen vor versehentlichem Parent-Wechsel zu schuetzen.

Toolbar (Detail-Seite)
Schlanke Toolbar oben rechts:
| Icon | Aktion (aria-label) | CASL | Wirkung |
|---|---|---|---|
| ← | Zurückgehen | — | Zurück zur Liste. |
| 🏠 | Zur Startseite gehen | — | Springt auf das Dashboard / /. |
| ⏮/◀/▶/⏭ | Pagination | — | Navigation durch die gefilterte Liste — Massen-Bearbeitung ohne Liste-Sprung. |
Globale Floating-Drawer (links)
Wie auf jeder Detail-Seite verfuegbar — siehe Floating-Quickbar:
- KAL. (Mini-Kalender)
- ZEIT (Persoenliche Wochen-Arbeitszeit)
- ARBEIT (Eigene bevorstehende Aufträge)
UI-Elemente
Button: „+ Neu"
Tab Standorte (innerhalb Kunde) oder unter /locations. Erfordert create:Location. Öffnet Detailseite mit customerId vorausgefuellt.
Felder und Eingaben
| Feldname | Pflicht | Datentyp | Beschreibung | Wirkung beim Ausfuellen | Voraussetzung |
|---|---|---|---|---|---|
locationNo | automatisch | String | Fortlaufend pro Kunde. Disabled. | Wird im beforeCreate-Hook aus MAX(parseInt(locationNo)) + 1 gesetzt. Erscheint in Auswahllisten und auf Belegen. | Bestehende Standorte des Kunden mit numerischen locationNo. |
name | nein | String | Standortname. | Anzeige in Auswahllisten und Reports. | — |
customerId | ja (disabled nach Create) | UUID | Parent-Kunde. | Bestimmt den Mandanten-Kontext und die Sichtbarkeit. Nach dem Speichern nicht mehr änderbar — schuetzt verknuepfte Belege/Anlagen. | view:Customer; Kunde muss aktiv sein. |
status | ja | Auswahl active/inactive | Aktivitaetsstatus. | inactive blendet den Standort in neuen Belegen/Aufträgen aus. Wird kaskadiert vom uebergeordneten Kunden gesetzt. | — |
vatId | nein | String(32) | USt-IdNr. (separat vom Kunden möglich). | Wird normalisiert. Bei innergemeinschaftlichen Belegen über den Standort wirkt diese USt-IdNr. statt der vom Kunden. | Format [ISO-Code][Ziffern]. |
latitude / longitude | nein | String | Geokoordinaten. | Anker für Karten-Visualisierungen und Routenoptimierung. | — |
Workflows und Zustaende
Status-Änderungen am Kunden kaskadieren auf Standorte (siehe Kunden).
Wiederverwendbare Konzepte
- Polymorpher Parent-Pattern — Standorte sind in
SalesDocument.parentTypeund inBankAssignment/ContactParent/ProductSpecialCondition/DocumentFolderreferenziert. - Berechtigungen verstehen (CASL)
Verknuepfungen zu anderen Modulen
- Kunden — Pflicht-Parent (
Location.customerId). - Anlagen / Systeme (
/systems) —System.locationId(1:N). - Aufträge — Workorder.locationId (1:N).
- Verkaufsbelege —
SalesDocument.parentType = 'Location'. - Bankverbindungen —
BankAssignment.parentType = 'Location'(eigene Bankdaten pro Standort möglich). - Dokumente — Auto-DocumentFolder beim Anlegen.
- CRM (
/locations/:id/crm) — bei aktivem CRM-Tracking trägt der Standort ein eigenes CRM-Profil (z. B. um Standorte eines Kunden separat zu verfolgen).
Häufige Fehler und Lösungen
| Fehler | Lösung |
|---|---|
customerId nicht änderbar | Per Design — Standort ist nach Anlage einem Kunden fest zugeordnet. |
| Änderungen werden nicht sofort sichtbar | Cache-Invalidate nach PATCH/POST/DELETE laeuft auf dem Server, GET-Antwort bei direktem Refresh kann kurz veraltet sein. |
locationNo springt | Auto-Generator zählt MAX(parseInt(locationNo)) + 1 — nicht-numerische Werte werden ignoriert. |
API/Schnittstellen
| Methode | Endpoint | Zweck | CASL |
|---|---|---|---|
GET | /api/locations | Liste | view Location |
GET | /api/locations/:id | Detail | view Location |
POST | /api/locations | Anlegen | create Location |
PATCH | /api/locations/:id | Ändern | update Location |
DELETE | /api/locations/:id | Soft-Delete | delete Location |
GET-Endpoints sind 300 s gecacht (cacheResponse-Middleware).
Versionshinweise
- 2026-06-24: CRM-Tab (
/locations/:id/crm) ergänzt — Standorte können ein eigenes CRM-Profil tragen. Verifiziert anLocationCrmPage.tsx. - 2026-04-29: Initiale Veroeffentlichung.