Resolution Codes API
Resolution Codes sind konfigurierbare Abschluss-/Lösungs-Codes pro Entitätstyp (Ticket, Incident, Problem) — z.B. FIXED, WORKAROUND, DUPLICATE. Sie steuern den Abschluss (RESOLVED/CLOSED): Sind für einen Entitätstyp Codes konfiguriert, ist beim terminalen Statuswechsel ein Code Pflicht. Jeder Code steuert zusätzlich das SLA-Verhalten und kann beim Kaskadieren über verlinkte Entitäten hinweg übernommen werden.
Authentifizierung & Permissions
Lesen ist für jeden eingeloggten Benutzer offen (die aktiven Codes werden in den Abschluss-Dialogen gebraucht). Inaktive Codes anzeigen sowie alle Schreib-Operationen erfordern settings.editGeneral. Details siehe Permissions & RBAC.
| Aktion | Permission |
|---|---|
| Aktive Codes lesen / Liste | jede Auth (Login) |
| Inaktive Codes mitlesen (?includeInactive) | settings.editGeneral |
| Erstellen / Aktualisieren / Deaktivieren | settings.editGeneral |
User-Kontext erforderlich (kein API-Key): Erstellen, Aktualisieren und Deaktivieren verlangen einen eingeloggten Benutzer. Ein X-API-Key wird hier mit 403 abgelehnt. GET-Routen sind auch ohne settings.editGeneral nutzbar (nur Login nötig) — außer ?includeInactive=true.
Endpoints Übersicht
| Method | Endpoint | Beschreibung | Permission |
|---|---|---|---|
GET | /api/resolution-codes | Liste (gruppiert nach Typ oder via ?entityType gefiltert) | jede Auth |
GET | /api/resolution-codes?entityType=TICKET | Nur aktive Codes dieses Typs (Array) | jede Auth |
GET | /api/resolution-codes?includeInactive=true | Inkl. inaktiver Codes (Settings-UI). Ein Entzug des Rechts wirkt hier sofort. | settings.editGeneral |
POST | /api/resolution-codes | Code erstellen (201). Ein bereits vorhandener Code ist 409 RESOLUTION_CODE_EXISTS. | settings.editGeneral |
PATCH | /api/resolution-codes/:id | Code aktualisieren | settings.editGeneral |
DELETE | /api/resolution-codes/:id | Deaktivieren (Soft-Delete, isActive=false) → 204. Der letzte aktive Code eines Typs lässt sich nicht deaktivieren (409 RESOLUTION_CODE_LAST_ACTIVE). | settings.editGeneral |
Ohne ?entityType liefert GET / ein nach Typ gruppiertes Objekt { "TICKET": [...], "INCIDENT": [...], "PROBLEM": [...] }; mit ?entityType ein flaches Array. Alle Listen sind nach sortOrder (aufsteigend) sortiert.
Felder
| Feld | Typ | Beschreibung |
|---|---|---|
entityType | enum | TICKET, INCIDENT, PROBLEM (bei Create Pflicht, danach unveränderlich) |
code | String (1–50) | UPPER_SNAKE_CASE (Regex ^[A-Z][A-Z0-9_]*$), eindeutig je entityType. Eingabe wird normalisiert (Bindestriche/Leerzeichen → _). |
label | JSON (i18n) | Lokalisierte Labels — de und en PFLICHT, fr/es/it optional |
description | JSON? (i18n) | Optionale lokalisierte Beschreibung |
isDefault | Boolean | Vorausgewählter Code — nur EINER pro entityType (Setzen entsetzt die anderen automatisch) |
isActive | Boolean | Aktiv. Soft-Delete setzt false; der letzte aktive Code kann nicht deaktiviert werden (409) |
sortOrder | Int | Reihenfolge im UI (Default 99 bei Create) |
requiresNote | Boolean | Erzwingt ein zusätzliches Pflicht-Textfeld bei Auswahl |
requiresLink | Boolean | Erzwingt Auswahl einer Master-Entität (z.B. DUPLICATE → Original verlinken) |
slaBehavior | enum | RESOLVE, CANCEL, EXCLUDE_FROM_REPORTING (Default RESOLVE) |
color | String? (≤20) | Badge-Farbe im UI (z.B. green, amber, red) |
Code erstellen
POST /api/resolution-codes
{
"entityType": "TICKET",
"code": "DUPLICATE",
"label": { "de": "Duplikat", "en": "Duplicate" },
"description": { "de": "Bereits in einem anderen Vorgang erfasst", "en": "Already tracked in another item" },
"isDefault": false,
"sortOrder": 30,
"requiresLink": true,
"slaBehavior": "CANCEL",
"color": "amber"
}
Response (201 Created)
{
"id": "clx...",
"entityType": "TICKET",
"code": "DUPLICATE",
"label": { "de": "Duplikat", "en": "Duplicate" },
"isDefault": false,
"isActive": true,
"sortOrder": 30,
"requiresNote": false,
"requiresLink": true,
"slaBehavior": "CANCEL",
"color": "amber"
}
code wird serverseitig normalisiert (Großschreibung, Bindestriche/Leerzeichen → Unterstrich). Ein bereits existierender Code für denselben entityType führt zu 409 Conflict.
Validierung & Anwendung (beim Abschließen)
Beim Wechsel auf RESOLVED oder CLOSED prüft das System den Code für Tickets, Incidents und Problems einheitlich:
- Sind für den Entitätstyp KEINE Codes konfiguriert → der Code ist optional.
- Sind Codes konfiguriert und der Übergang ist terminal, aber kein Code übergeben →
400 RESOLUTION_CODE_REQUIRED. - Unbekannter oder deaktivierter Code →
400 INVALID_RESOLUTION_CODE. Beide Fehler tragen details mit entityType, code und reason. - Gültiger Code → wird normalisiert übernommen; slaBehavior bestimmt das SLA-Verhalten, requiresNote/requiresLink lassen die Oberfläche zusätzlich Notiz bzw. Verknüpfung abfragen.
SLA-Verhalten
slaBehavior |
Wirkung |
|---|---|
RESOLVE | Normaler Abschluss — SLA gilt als erfüllt (Default) |
CANCEL | SLA wird abgebrochen/storniert (z.B. DUPLICATE, kein echter Abschluss) |
EXCLUDE_FROM_REPORTING | Vorgang wird aus dem SLA-Reporting ausgeschlossen |
Cascading-Mapping (Problem→Incident→Ticket)
Beim Kaskadieren und beim Batch-Resolve wird der Resolution-Code der Quell-Entität so auf die Ziel-Entität übertragen:
- Existiert derselbe Code aktiv beim Ziel-Typ → er wird direkt übernommen.
- Sonst → der Default-Code des Ziel-Typs (Fallback FIXED, falls kein Default).
- Der ursprüngliche Quell-Code bleibt zur Transparenz in der Activity erhalten.
Siehe Cascading System und Entity Linking API (batch-resolve, DUPLICATE).
Audit & UI
- Audit: Änderungen werden als ADMIN / RESOLUTION_CODE (RESOLUTION_CODE_CREATED / _UPDATED) geloggt.
- UI: Admin-Center → Service-Konfiguration → Lösungscodes (
/admin/resolution-codes)