Eviworx
Docs

Inventory API

Die Inventory API steuert Inventur-Sessions (Stocktake): Beim Start wird ein Snapshot der erwarteten Assets gezogen, anschließend werden Assets per QR-/Tag-Scan erfasst. Aus Soll (Snapshot) und Ist (Scans) ergeben sich fehlende und unerwartete Assets. Scope ist entweder ein Standort (alle Assets einer Location) oder ein Benutzer (dessen zugewiesene Assets).

📦
Funktionen
✓ Scope: Standort oder Benutzer
✓ Soll-Ist-Snapshot beim Start
✓ Scan per QR/Asset-Tag
✓ Mengen für Consumables (quantity/expectedQty)
✓ Fehlende & unerwartete Assets
✓ Self-Service (eigene Session) + Agent-Review
✓ Rescan-Verhalten: OVERWRITE / ACCUMULATE
✓ Report + Scan-Statistik
✓ Automatische Erfassung verbauter Komponenten
✓ Missing mit Live-Status + „Als verloren melden"

Lebenszyklus

Start (Snapshot erwarteter Assets)   │  POST /api/inventory-sessions
   ▼
ACTIVE ──scannen──▶ POST /:id/scan  (pro Asset, unique je Session)
   │  POST /:id/ready-for-review   (Scanner übergibt zur Prüfung)
   ▼
READY FOR REVIEW
   │  POST /:id/complete           (Agent schließt ab → endedAt gesetzt)
   ▼
COMPLETED   → Notification INVENTORY_SESSION_COMPLETED an Ersteller

rescanBehavior: OVERWRITE (Default) — ein erneuter Scan desselben Assets überschreibt den vorherigen (ein Eintrag je Session+Asset). ACCUMULATE — Mehrfach-Scans addieren die Mengen (für Verbrauchsmaterial/Consumables).

Authentifizierung & Permissions

Self-Service ist eingebaut: Endbenutzer dürfen eine Session für SICH starten, scannen und zur Prüfung übergeben — aber nicht abschließen oder fremde Sessions sehen. Abschluss, Scan-Korrekturen und Reports sind Agent-/Admin-Rechte. Permissions & RBAC.

PermissionBeschreibung
inventory.startSessionSession für andere/Standort starten
inventory.startOwnSessionEigene Session starten (Self-Service, Default an)
inventory.scanAssets scannen + Scan-Notiz, ready-for-review
inventory.viewSessions / viewOwnSessionsAlle bzw. nur eigene Sessions sehen
inventory.completeSessionsSession abschließen
inventory.editScansScans korrigieren/löschen
inventory.viewReports / exportReportsReport ansehen / exportieren
inventory.viewDeleted / restorePapierkorb sehen / Session wiederherstellen (beide Default aus)

Zum Wiederherstellen sind zwei Rechte nötig: inventory.restore für die Aktion selbst und inventory.viewDeleted, um den Papierkorb zu sehen — wer den Papierkorb nicht sehen darf, holt auch nichts daraus zurück. Zusätzlich gilt dieselbe Sichtbarkeit wie in der Liste: Wiederherstellen lässt sich nur, was man auch sehen darf. Beide Rechte sind standardmäßig aus; nur die Administrator-Systemrolle erhält sie automatisch.

Endpoints Übersicht

Mount: /api/inventory-sessions

Method Endpoint Beschreibung Permission
POST/Session starten (Snapshot erwarteter Assets) → 201, Session-ObjektstartSession / startOwnSession
GET/Sessions auflisten — { data, pagination, counts }; ?q, ?page/per, ?sort, ?f.<feld>, ?status=active|completed, ?deleted=1viewSessions / viewOwnSessions
GET/:idSession-Detailview…
PATCH/:idSession-Metadaten ändernstartSession
POST/:id/ready-for-reviewZur Prüfung übergebenscan
POST/:id/completeSession abschließen (endedAt)completeSessions
DELETE/:idSession in den Papierkorb legen (Soft-Delete, auch abgeschlossene; Scans bleiben) → 204startSession / startOwnSession (nur eigene Session: gestartet oder Ziel-Benutzer)
POST/:id/restoreSession aus dem Papierkorb zurückholenrestore + viewDeleted
POST/:id/scanAsset scannen — assetId ODER code (gescannter QR-/Barcode-Wert), dazu quantity, notescan
PATCH/:id/scans/:scanIdScan korrigieren (Menge)editScans
PATCH/:id/scans/:scanId/noteScan-Notiz setzenscan
DELETE/:id/scans/:scanIdScan löschen → 204editScans
GET/:id/scansScans der Session — { data, pagination }view…
GET/:id/scans/statsScan-Statistikview…
GET/:id/unexpectedGescannt, aber nicht erwartet — { data, pagination }view…
GET/:id/missingErwartet, aber nicht gescannt — { data, pagination }view…
GET/:id/reportInventur-Report (Soll-Ist)viewReports

Felder

InventorySession

FeldTypBeschreibung
nameStringz.B. „Inventur Q4 2026 – Serverraum"
scopeTypeenumLOCATION, USER
locationIdString?bei Scope LOCATION (Asset-Standort)
userIdString?bei Scope USER (dessen Assets)
expectedAssetIdsString[]Snapshot der Soll-Asset-IDs beim Start
expectedSnapshotJSONVollständiger Soll-Snapshot (assetTag, name, quantity …)
rescanBehaviorenumOVERWRITE (default), ACCUMULATE
readyForReviewAt / ByDateTime? / String?Übergabe zur Prüfung
dueAtDateTime?Frist für die Inventur — setzen und ändern darf sie nur inventory.startSession (403 INVENTORY_DUE_AT_FORBIDDEN); der Ziel-Benutzer kann seine eigene Frist also nicht verschieben
deletedAtDateTime?gesetzt, solange die Session im Papierkorb liegt
startedBy / startedAt / endedAtErsteller, Start, Abschluss (endedAt = abgeschlossen)

Fristen-Überwachung: Ein Built-in-Cronjob („Inventory Due Monitoring", stündlich, standardmäßig aktiv) meldet nahende und überschrittene Fristen: drei Tage und einen Tag vorher, danach überfällig. Jeder Meilenstein wird nur einmal gemeldet. Empfänger ist der Ziel-Benutzer bzw. der Starter der Session — bei Überfälligkeit zusätzlich der Starter. Ohne gesetztes dueAt passiert nichts. CronJobs API.

InventoryScan

FeldTypBeschreibung
assetIdStringGescanntes Asset (unique je Session — siehe rescanBehavior)
quantityIntGezählte Menge (Default 1)
expectedQtyInt?Erwartete Menge aus dem Snapshot
scanCountIntWie oft dieses Asset in der Session gescannt wurde
noteString?Notiz zum Scan
scannedBy / scannedAtWer/wann gescannt

Fehlende Assets, Live-Status & Auto-Account

  • Statischer Missing-Snapshot: Das Soll bleibt unverändert (Inventur-Protokoll) — ein während der Session z.B. als LOST gemeldetes Asset bleibt im Missing-Tab und -Zähler.
  • Live-Status (currentStatus): Beim Lesen werden Missing-Zeilen mit dem aktuellen Asset-Status annotiert („inzwischen LOST / zurückgenommen"); undefined = Asset inzwischen gelöscht.
  • Automatische Erfassung (Auto-Account): Eine nicht gescannte Komponente gilt als automatisch erfasst, wenn ihr Container in der Session gescannt wurde (auch über mehrere Ebenen, über die Relationen PART_OF/INSTALLED_ON). Die Komponente wird dabei nur als erfasst markiert; ein Scan wird nicht angelegt. Komponenten ohne Container-Relation bleiben fehlend. Komponenten außer Betrieb (LOST/RETIRED/DISPOSED) werden NICHT automatisch erfasst — sie bleiben fehlend und tragen ein currentStatus-Badge.

Dadurch trennt GET /:id/scans/stats echte von auto-erfassten Missing: { scanned, expected, missing, autoAccounted, unexpected }. GET /:id/missing liefert missing (nur ECHTE Missing) plus autoAccountedAssets; jede Missing-Zeile trägt currentStatus und ggf. autoAccountedVia.

Asset-Bewegungen aus der Inventur

Die Inventur-Routen bewegen KEINE Assets — es gibt keinen Bewegungs-Endpoint unter /api/inventory-sessions. Aktionen an gescannten, unerwarteten oder fehlenden Assets laufen über die Asset-Flow-Endpunkte (es gelten die assets.*-Rechte, nicht inventory.*). Welche Aktion angeboten wird, hängt von Session-Ziel, Tracking-Modus und Status des Assets ab; Zuweisungen laufen dabei immer über Ausgabe, Installation oder Rücknahme:

KontextAktionAPI
Unerwartet · USER-Scope · PERSON · user-losAn {User} ausgebenPOST /assets/:id/checkout
Unerwartet · USER-Scope · PERSON · IN_USE (anderer User)Besitzer wechselncheckin + checkout (+ Komponenten via coReturn/coMove)
Unerwartet · LOCATION-Scope · LOCATION AVAILABLEHier installierenPOST /assets/:id/install
Unerwartet · LOCATION-Scope · IN_USE woandersStandort korrigierenPATCH /assets/:id { locationId, coLocateAssetIds? }
Fehlend (beide Scopes)Als verloren meldenPATCH /assets/:id { status: LOST, note }
PERSON IN_USEZurücknehmenPOST /assets/:id/checkin
Sperr-Zustände: bei offener Übergabe (PENDING_ACCEPTANCE / RETURN_PENDING) ist nur „Detail öffnen" möglich. Details zu den Flows: Asset-Lebenszyklus.

Beispiel-Flow

# 1. Start a session for a location
POST /api/inventory-sessions
{ "name": "Stocktake Q4 2026 – Server Room", "scopeType": "LOCATION", "locationId": "clx-loc-id", "rescanBehavior": "OVERWRITE" }

# 2. Scan asset (QR → assetId)
POST /api/inventory-sessions/:id/scan
{ "assetId": "clx-asset-id", "quantity": 1, "note": "Rack 3" }

# 3. Hand off for review
POST /api/inventory-sessions/:id/ready-for-review

# 4. Check expected vs actual
GET /api/inventory-sessions/:id/missing      # expected, not scanned
GET /api/inventory-sessions/:id/unexpected   # scanned, not expected

# 5. Agent completes
POST /api/inventory-sessions/:id/complete
Assets API →
Asset-Tags/QR, Standorte, Zuweisung
Permissions & RBAC →
Self-Service vs. Agent-Rechte
Notifications →
INVENTORY_SESSION_COMPLETED