Vergleich mit InvenTree, Snipe-IT, Grocy, Shelf.nu, Resgrid, KP Front, FleetMS, HiOrg-Server ergibt neue Kacheln (ASSET-010 Custody, FILE-008 Hash-Audit-Journal, FILE-009 Notizen, NOTIF-003, MAINT-007 Tankbuch, ZUST-003 Standort-Scoping, FOUND-007 Import/Export, FOUND-008 Fristen-Dienst, READY-006 Statistik-Dashboard, UI2-006..010) sowie Referenz-Ergänzungen bei bestehenden Lücken. Alle Design- Entscheidungen (Datenmodell, Sicherheitsanforderungen bei ASSET-010) geklärt. Neues Epic 23 (Flutter-Begleit-App, Sondierungs-Prototyp FLUT-001) inkl. geklärtem TLS-Blocker (Domain mabea.perlbach-edv.de mit Let's-Encrypt-Zertifikat statt selbstsigniertem Server-Zertifikat). Alle Kacheln bleiben offen/ungeplant, nur ausgearbeitet, keine Implementierung. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
361 lines
21 KiB
Markdown
361 lines
21 KiB
Markdown
# Epic 04 — Assets
|
|
|
|
Details zu ASSET-001 … ASSET-010. ASSET-010 ergänzt am 2026-09-09 aus Open-Source-Vergleich
|
|
(Shelf.nu Custody-Feature), noch offen/ungeplant.
|
|
|
|
---
|
|
|
|
## ASSET-001 — AssetCategory
|
|
|
|
- **Ziel:** Oberste Gliederungsebene für Ressourcentypen.
|
|
- **Beschreibung:** Kategorie-Stammdaten (z.B. „Medizin", „Fahrzeuge", „Funk").
|
|
- **Benutzerwert:** Navigierbare Struktur beim Anlegen/Suchen.
|
|
- **Abhängigkeiten:** FOUND-002
|
|
- **Datenmodell:** `asset_category` (id, name)
|
|
- **Backend:** CRUD
|
|
- **Frontend:** Verwaltung Kategorie
|
|
- **Mobile:** nur Anzeige/Filter
|
|
- **QR-Code/Seriennummer/Inventarnummer:** nein
|
|
- **Akte:** nein direkt
|
|
- **Rechte:** Administrator
|
|
- **Audit:** Änderung geloggt
|
|
- **Akzeptanzkriterien:** Kategorie anlegen/umbenennen/löschen (nur wenn unbenutzt).
|
|
- **Tests:** CRUD-Test, Löschschutz-Test bei Verwendung.
|
|
- **DoD:** mind. 3 Beispielkategorien angelegt.
|
|
|
|
## ASSET-002 — AssetType
|
|
|
|
- **Ziel:** Konkreter Typ innerhalb einer Kategorie (z.B. „AED Philips FRx").
|
|
- **Beschreibung:** Typ-Stammdaten, verweist auf Kategorie + Hersteller/Modell (IDENT-005).
|
|
- **Benutzerwert:** Wiederverwendbare Vorlage für alle Exemplare dieses Typs.
|
|
- **Abhängigkeiten:** ASSET-001
|
|
- **Datenmodell:** `asset_type` (id, category_id, name, hersteller_id, modell)
|
|
- **Backend:** CRUD
|
|
- **Frontend:** Verwaltung
|
|
- **Mobile:** Anzeige
|
|
- **QR-Code/Seriennummer/Inventarnummer:** nein direkt
|
|
- **Akte:** Stammdatenbereich referenziert den Typ
|
|
- **Rechte:** Materialwart/Administrator
|
|
- **Audit:** Änderung geloggt
|
|
- **Akzeptanzkriterien:** Typ anlegen mit Kategorie- und Hersteller-Verknüpfung.
|
|
- **Tests:** CRUD- + Verknüpfungstest.
|
|
- **DoD:** mind. ein Typ je Kategorie angelegt.
|
|
|
|
## ASSET-003 — Asset/AssetInstance
|
|
|
|
- **Ziel:** Das konkrete Einzelobjekt (physische Ressource) — Kernentität der Plattform.
|
|
- **Beschreibung:** Instanz eines AssetType mit eigener Objekt-ID, Inventarnummer,
|
|
Seriennummer.
|
|
- **Benutzerwert:** „Ein Ding, ein Datensatz" — Grundlage für praktisch alle anderen Epics.
|
|
- **Abhängigkeiten:** ASSET-002, IDENT-001/002/004
|
|
- **Datenmodell:** `asset` (id, asset_type_id, inventarnummer, seriennummer, status, ...)
|
|
- **Backend:** CRUD
|
|
- **Frontend:** Anlegen-Formular, Liste
|
|
- **Mobile:** Anzeige/Anlage im Feld
|
|
- **QR-Code:** wird für diese Instanz erzeugt (IDENT-006)
|
|
- **Seriennummer/Inventarnummer:** hier verortet
|
|
- **Akte:** 1:1 Grundlage der Akte
|
|
- **Rechte:** Materialwart/Administrator schreibt, alle lesen
|
|
- **Audit:** Anlage/Änderung geloggt
|
|
- **Akzeptanzkriterien:** Asset anlegen mit Typ-Referenz, Inventarnummer/SN eindeutig im
|
|
jeweiligen Scope.
|
|
- **Tests:** CRUD-Test, Eindeutigkeits-Constraint-Test.
|
|
- **DoD:** durchgängig mit IDENT-001/002/004 verzahnt getestet.
|
|
|
|
## ASSET-004 — Asset-Status-Modell
|
|
|
|
- **Ziel:** Genereller Lebenszyklus-Status, den alle Ressourcentypen teilen.
|
|
- **Beschreibung:** Enum z.B. AKTIV/IN_WARTUNG/AUSSER_DIENST — Erweiterungspunkt für
|
|
Readiness; spezifische Module wie Fleet dürfen feiner erweitern (FLEET-004).
|
|
- **Benutzerwert:** Einheitliche Sprache über alle Ressourcentypen hinweg.
|
|
- **Abhängigkeiten:** ASSET-003
|
|
- **Datenmodell:** `asset.status` (enum)
|
|
- **Backend:** Statuswechsel-Endpoint
|
|
- **Frontend:** Status-Dropdown
|
|
- **Mobile:** Anzeige/Änderung
|
|
- **QR-Code/Seriennummer/Inventarnummer:** nein
|
|
- **Akte:** Stammdatenbereich (Status-Badge)
|
|
- **Rechte:** Materialwart/Administrator
|
|
- **Audit:** Statuswechsel geloggt
|
|
- **Akzeptanzkriterien:** Statuswechsel möglich, ungültige Übergänge (falls modelliert)
|
|
abgelehnt.
|
|
- **Tests:** Statuswechsel-Test.
|
|
- **DoD:** Status fließt sichtbar in FILE-002 ein.
|
|
|
|
## ASSET-005 — Asset-Suche & Liste
|
|
|
|
- **Ziel:** Ressourcen wiederfinden, ohne ihre Akte-ID einzeln zu kennen.
|
|
- **Beschreibung:** Liste mit Filter (Kategorie/Typ/Status) + Volltextsuche
|
|
(Name/Inventarnummer/SN).
|
|
- **Benutzerwert:** Alltagswerkzeug für Materialwart/Helfer.
|
|
- **Abhängigkeiten:** ASSET-003
|
|
- **Datenmodell:** keins neu
|
|
- **Backend:** Such-/Filter-Query-Parameter am Listen-Endpunkt
|
|
- **Frontend:** Listen-Seite mit Suchfeld/Filtern
|
|
- **Mobile:** kompakte Listenansicht
|
|
- **QR-Code:** nein
|
|
- **Seriennummer/Inventarnummer:** Suchfelder
|
|
- **Akte:** Sprungziel je Zeile
|
|
- **Rechte:** wie Lese-Recht
|
|
- **Audit:** nein
|
|
- **Akzeptanzkriterien:** Suche nach Inventarnummer/SN/Name liefert korrekte Treffer.
|
|
- **Tests:** Suchtest mit kombinierten Kriterien.
|
|
- **DoD:** Performance akzeptabel bei realistischer Datenmenge (Index statt
|
|
Volltabellen-Scan).
|
|
|
|
## ASSET-006 — Asset-Bewegungshistorie
|
|
|
|
- **Ziel:** Generisches Standortwechsel-Protokoll für jedes Asset, nicht nur
|
|
fahrzeug-/warehouse-spezifisch.
|
|
- **Beschreibung:** Bewegung(asset_id, von, nach, wer, wann, warum) — Basis für
|
|
WH-007/FILE-003.
|
|
- **Benutzerwert:** Nachvollziehbarkeit „wo war das Ding wann".
|
|
- **Abhängigkeiten:** ASSET-003, WH-001
|
|
- **Datenmodell:** `asset_bewegung`
|
|
- **Backend:** Bewegung erzeugen bei Standortwechsel
|
|
- **Frontend:** Verschieben-Aktion
|
|
- **Mobile:** ggf. später (P2)
|
|
- **QR-Code/Seriennummer/Inventarnummer:** nein
|
|
- **Akte:** Standort- und Historienbereich
|
|
- **Rechte:** Materialwart+
|
|
- **Audit:** eigenständiges Fach-Protokoll (nicht generisches Audit-JSON, da Von/Nach-Felder
|
|
strukturiert gebraucht werden — bewusst getrennt von FOUND-006)
|
|
- **Akzeptanzkriterien:** Standortwechsel erzeugt Bewegungseintrag korrekt.
|
|
- **Tests:** Bewegungstest.
|
|
- **DoD:** funktional deckungsgleich mit dem in MABEA bereits existierenden
|
|
Lagerbewegung-Modell (dient hier als Vorbild/Referenzimplementierung).
|
|
|
|
## ASSET-007 — AssetSet
|
|
|
|
- **Ziel:** Mehrere Assets als ein handhabbares Bündel (Materialset) verwalten.
|
|
- **Beschreibung:** Set-Entität mit Mitgliedsliste (Assets oder Consumables in bestimmter
|
|
Menge).
|
|
- **Benutzerwert:** z.B. „Verbandsset" als eine Ausgabeeinheit statt Einzelteile einzeln zu
|
|
handhaben.
|
|
- **Abhängigkeiten:** ASSET-003
|
|
- **Datenmodell:** `asset_set`, `asset_set_mitglied`
|
|
- **Backend:** CRUD Set + Mitglieder
|
|
- **Frontend:** Set-Zusammenstellung
|
|
- **Mobile:** Anzeige
|
|
- **QR-Code:** Set kann eigene Identität/eigenen QR bekommen (IDENT-001 anwendbar)
|
|
- **Seriennummer/Inventarnummer:** Set selbst kann eigene Inventarnummer haben
|
|
- **Akte:** eigene Akte für das Set
|
|
- **Rechte:** Materialwart+
|
|
- **Audit:** Änderung der Mitgliederliste geloggt
|
|
- **Akzeptanzkriterien:** Set anlegen, Mitglieder hinzufügen/entfernen.
|
|
- **Tests:** CRUD-Test.
|
|
- **DoD:** mind. ein Set mit 2+ Mitgliedern funktionsfähig. **Lücke gegenüber MABEA:**
|
|
Beladungsvorlage ist konzeptionell ähnlich, aber fest ans Objekt gebunden — kein
|
|
eigenständiges, wiederverwendbares Set-Konzept.
|
|
- **Referenz (Open-Source-Vergleich 2026-09-09):** Shelf.nu (`shelf-nu/shelf.nu`) nennt
|
|
dasselbe Konzept „Kits" — Assets zu einer wiederverwendbaren Einheit bündeln
|
|
(Laptop+Charger+Dock). Bestätigt den Bedarf, löst aber keine MABEA-spezifische Frage
|
|
zusätzlich (Set-Aufbau bleibt wie hier beschrieben).
|
|
|
|
## ASSET-010 — Custody/Ausgabe an Person (P2, neu, vollständig ausgearbeitet 2026-09-09)
|
|
|
|
- **Ziel:** Nachvollziehen, welche Person ein bestimmtes Einzelgerät aktuell
|
|
persönlich in Verwahrung hat — unabhängig vom Standort-/Objekt-bezogenen
|
|
ZUST-001 und von der reinen Kontroll-**Zuständigkeit** in ZUST-002.
|
|
- **Abgrenzung zu ZUST-002 (geklärt 2026-09-09):** ZUST-002 sagt „Max soll den
|
|
Notfallkoffer #12 kontrollieren" — das Objekt bleibt am Standort, jeder darf es
|
|
trotzdem kontrollieren, reine Empfehlung ohne Zugriffssperre. ASSET-010 sagt „Max
|
|
hat Funkgerät #7 heute persönlich dabei" — das Gerät wandert physisch mit der
|
|
Person, bis sie es zurückgibt; danach kann es an jemand anderen ausgegeben
|
|
werden. Unterschiedliche Konzepte (Kontroll-Zuständigkeit vs. physischer Besitz),
|
|
echter Bedarf bestätigt — kein Duplikat.
|
|
- **Ziel-Entität (geklärt 2026-09-09): `GeraetInstanz`, nicht generisches `Objekt`.**
|
|
`GeraetInstanz` hängt an einer `Objektposition` und trägt die eigene
|
|
Seriennummer (`backend/app/models/geraet_instanz.py`) — genau das einzelne,
|
|
seriennummerpflichtige Gerät (Funkgerät, Atemschutzgerät), das eine Person
|
|
persönlich mitführt. Ein ganzes `Objekt` (z.B. ein Fahrzeug oder ein
|
|
Materiallager) wird nicht „mitgeführt" — dafür ist Custody nicht gedacht.
|
|
- **Beschreibung:** Ausgabe-/Rücknahme-Vorgang je `GeraetInstanz` an eine `Person`
|
|
(PERS-001), mit Zeitstempel, Bestätigungsmechanismus (siehe unten) und Verlauf.
|
|
- **Benutzerwert:** Bei Verlust/Defekt sofort klar, wer das Gerät zuletzt hatte,
|
|
ohne Rückfrage-Runde.
|
|
- **Bestätigungsmechanismus bei Ausgabe (überarbeitet 2026-09-09, final 2026-09-09
|
|
— Unterschrift OPTIONAL pro Ausgabe, cross-device per QR-Scan):**
|
|
- Unterschrift/Protokoll ist **keine Pflicht für jede Ausgabe**, sondern eine
|
|
Entscheidung der ausgebenden Stelle im Moment der Ausgabe — Toggle „Mit
|
|
Protokoll+Unterschrift" im Ausgabe-Dialog. Ohne Toggle: einfache,
|
|
formlose Ausgabe wie ursprünglich geplant (nur Custody-Zeile, kein PDF, kein
|
|
QR-Signier-Flow) — schnelle Übergabe für den Alltag. Mit Toggle: voller
|
|
Signier-Flow inkl. PDF-Protokoll, gedacht für kritisches/hochwertiges
|
|
Material oder wenn die ausgebende Stelle es für nötig hält.
|
|
- **Ablauf (nur wenn „Mit Protokoll" gewählt):** Portal (Tablet/Desktop der
|
|
ausgebenden Stelle) zeigt nach Auswahl
|
|
von Gerät+Empfänger einen QR-Code an, der auf eine einmalig gültige,
|
|
kurzlebige Signier-Seite verweist (Token-basiert, kein Login nötig — die
|
|
Legitimation ist der physische Besitz des Tablets der ausgebenden Stelle +
|
|
der QR-Code selbst). Empfänger scannt den QR-Code mit dem **eigenen** Handy,
|
|
öffnet die Signier-Seite, unterschreibt dort per Touch-Canvas auf dem eigenen
|
|
Gerät (hygienischer/praktischer als eine geteilte Tablet-Oberfläche), sendet
|
|
ab. Das Portal erkennt den Abschluss (Polling auf den Ausgabe-Status) und
|
|
zeigt „unterschrieben ✓" an, danach gilt die Ausgabe als abgeschlossen.
|
|
- Signier-Token: einmalig verwendbar, kurze Lebensdauer (z.B. 5 Minuten), an
|
|
genau einen Ausgabevorgang gebunden — verhindert Wiederverwendung/Weitergabe
|
|
des Links.
|
|
- Aus Signatur + Geräte-/Personendaten + Zeitstempel wird automatisch ein
|
|
**Ausgabeprotokoll** (PDF) generiert und über den DOC-001-Mechanismus am
|
|
Custody-Eintrag UND in der Akte des Geräts abgelegt.
|
|
- Bei Rücknahme: dieselbe Wahl gilt spiegelbildlich — wurde die Ausgabe mit
|
|
Protokoll gemacht, läuft die Rücknahme ebenfalls über QR-Code→eigenes
|
|
Handy→Unterschrift→Rückgabeprotokoll. Wurde die Ausgabe formlos gemacht,
|
|
ist auch die Rücknahme formlos (kein nachträglicher Zwang zum Protokoll).
|
|
- **Sicherheitsanforderungen (Security-Review 2026-09-09, owasp-top10-expert —
|
|
verbindlich für die Implementierung, kein Nice-to-have):**
|
|
1. **Token:** `secrets.token_urlsafe(32)` (256 Bit), serverseitig nur als
|
|
SHA-256-Hash gespeichert (wie ein Passwort-Reset-Token) — Klartext existiert
|
|
nur im QR-Code/URL, nie in Logs. Access-Logs dieser Route ohne Query-String
|
|
protokollieren.
|
|
2. **Route:** Token als Pfad-Parameter (`/signieren/{token}`), nicht Query —
|
|
Query-Strings landen häufiger in Logs/Referrer/Browser-History.
|
|
`slowapi`-Rate-Limit pro IP UND pro Token (z.B. 10/Minute). Lookup
|
|
ausschließlich über Token-Hash, niemals über fortlaufende Custody-ID (IDOR).
|
|
3. **Race Condition:** Token-Verwendung als atomares DB-Update, nicht
|
|
Read-then-Write — `UPDATE ... WHERE token_hash=$1 AND status='ausstehend'`,
|
|
Rowcount prüfen statt separatem Check+Write.
|
|
4. **QR-Abfoto-Risiko:** bewusst akzeptiertes Restrisiko, **kein zusätzlicher
|
|
PIN-Schritt** (Entscheidung 2026-09-09 — Reibung im Feldeinsatz wiegt
|
|
schwerer, Ausgabe findet ohnehin unter Aufsicht der ausgebenden Stelle
|
|
statt, die den Vorgang beobachtet). 5-Minuten-Ablauf + Einmalverwendung des
|
|
Tokens bleiben als Grundschutz bestehen.
|
|
5. **Transport:** HTTPS zwingend (ohnehin nur über nginx-TLS erreichbar).
|
|
`VITE_API_BASE_URL` bleibt relativ (`/api/v1`) — Empfänger-Handy nutzt
|
|
dieselbe Domain/dasselbe TLS-Zertifikat. Explizit auf echtem Fremdgerät
|
|
testen, nicht nur localhost.
|
|
6. **Datensparsamkeit (DSGVO):** GET-Endpunkt der Signier-Seite liefert nur
|
|
Minimaldaten (Gerätebezeichnung, Empfängername, Zeitfenster) — keine
|
|
vollständige Custody-Historie, keine internen IDs. Bei ungültigem/
|
|
abgelaufenem/bereits verwendetem Token identische generische Fehlermeldung
|
|
(kein Enumerieren des Status). Signatur/PDF nach Abschluss nicht mehr über
|
|
denselben Token abrufbar — Download nur im authentifizierten Portal-Bereich.
|
|
7. **PDF-Generierung:** falls HTML-basiert (`weasyprint`) — Jinja2-Autoescape
|
|
aktiv lassen, kein `|safe` auf Nutzereingaben. Signatur-Bild serverseitig
|
|
validieren (Magic-Bytes/Größe/Dimensionen), bevor es ins PDF eingebettet
|
|
wird — keine beliebigen Datei-URLs oder SVG mit Skript zulassen.
|
|
- **Abhängigkeiten:** ASSET-003, PERS-001, DOC-001 (Ausgabeprotokoll-PDF), FOUND-002
|
|
(Signier-Token braucht eigene, kurzlebige Tabelle/Cache)
|
|
- **Datenmodell:** `geraet_instanz_custody` (geraet_instanz_id →
|
|
`geraet_instanz.id`, person_id, ausgegeben_am, ausgegeben_von_benutzer_id,
|
|
mit_protokoll: bool (Toggle-Entscheidung der ausgebenden Stelle),
|
|
ausgabeprotokoll_dokument_id nullable FK auf `dokument` (nur bei
|
|
`mit_protokoll=true`), zurueckgegeben_am nullable,
|
|
zurueckgenommen_von_benutzer_id nullable, rueckgabeprotokoll_dokument_id
|
|
nullable) — aktuelle Inhaberschaft = Zeile mit `zurueckgegeben_am IS NULL`.
|
|
`signier_token` (token, custody_id, ablauf_am, verwendet: bool) — nur relevant
|
|
wenn `mit_protokoll=true`, kurzlebig, kann nach Ablauf/Verwendung gelöscht
|
|
werden (kein Langzeit-Speicherbedarf).
|
|
- **Backend:** Ausgabe-Endpoint verzweigt nach `mit_protokoll` — `false`: Custody-
|
|
Zeile direkt als abgeschlossen anlegen (formlose Ausgabe, wie ursprünglich
|
|
geplant); `true`: Custody-Zeile unsigniert anlegen + Signier-Token erzeugen,
|
|
QR-Code-Inhalt zurückgeben, öffentlicher (token-authentifizierter, kein Login)
|
|
Signier-Endpoint nimmt Signatur-PNG entgegen, erzeugt PDF, markiert Custody als
|
|
abgeschlossen, Status-Polling-Endpoint fürs Portal. In beiden Fällen: verhindert
|
|
Doppel-Ausgabe (GeraetInstanz nur an eine Person gleichzeitig, DB-Constraint:
|
|
max. eine offene Zeile je `geraet_instanz_id`); bei `mit_protokoll=true`
|
|
zusätzlich Token-Ablauf serverseitig erzwungen (abgelaufene Tokens/unsignierte
|
|
Ausgaben nach Timeout verwerfen)
|
|
- **Frontend:** Ausgabe-Dialog am Gerät — Person auswählen, Toggle „Mit
|
|
Protokoll+Unterschrift"; bei aktiviertem Toggle QR-Code anzeigen →
|
|
Warten-auf-Signatur-Status, sonst sofortiger Abschluss. Separate mobile
|
|
Signier-Seite (eigenständige Route, kein Admin-Layout, funktioniert auf jedem
|
|
Handy-Browser ohne Login) nur relevant bei aktiviertem Toggle.
|
|
- **Mobile:** Ausgabe-Start per QR-Scan am Gerät selbst (wie gehabt), Signatur
|
|
läuft auf dem Empfänger-Handy über die separate Signier-Seite
|
|
- **QR-Code:** zwei unterschiedliche QR-Codes im Spiel — (1) Geräte-QR zum
|
|
Auswählen des Geräts (bestehender Mechanismus), (2) neuer Signier-Token-QR zum
|
|
Öffnen der Signier-Seite auf dem Empfänger-Handy
|
|
- **Seriennummer/Inventarnummer:** nutzt bestehende `GeraetInstanz`-Identität
|
|
- **Akte:** eigener Custody-Verlauf im Akte-Historienbereich (FILE-005)
|
|
- **Rechte:** Ausgabe/Rücknahme: Mitarbeiter+; Korrektur: Materialverantwortlicher+
|
|
- **Audit:** jede Ausgabe/Rücknahme geloggt, inkl. Zeitpunkt der Signatur
|
|
- **Akzeptanzkriterien:** Gerät kann nicht an zwei Personen gleichzeitig ausgegeben
|
|
sein; formlose Ausgabe (`mit_protokoll=false`) ist sofort abgeschlossen, kein
|
|
Signier-Flow ausgelöst; Ausgabe mit Protokoll ohne abgeschlossene Signatur gilt
|
|
nicht als abgeschlossen (Gerät bleibt bis zur Signatur „in Ausgabe schwebend",
|
|
nicht schon fest zugeordnet); abgelaufener/bereits verwendeter Signier-Token
|
|
wird abgelehnt; Ausgabeprotokoll-
|
|
PDF enthält Geräte-, Personen-, Zeit- und Signaturdaten; Verlauf zeigt lückenlose
|
|
Kette.
|
|
- **Tests:** Doppel-Ausgabe-Ablehnung, abgelaufener-Token-Ablehnungstest, bereits-
|
|
verwendeter-Token-Ablehnungstest, PDF-Generierungstest, Ausgabe→Signatur→
|
|
Rücknahme→Signatur→Neuausgabe-Zyklus, Race-Condition-Test (paralleler Request
|
|
auf denselben Token, nur einer darf gewinnen), Rate-Limit-Test, IDOR-Test
|
|
(Token-Lookup nur über Hash, keine ID-Erratbarkeit), Signatur-Bild-Validierungs-
|
|
test (ungültige/manipulierte Datei wird abgelehnt).
|
|
- **DoD:** offen — Design vollständig geklärt (2026-09-09), bereit für
|
|
Implementierung. **Referenz (Open-Source-Vergleich 2026-09-09):** Shelf.nu
|
|
(`shelf-nu/shelf.nu`, AGPL-3.0 — nur Konzeptvorbild, keine Codeübernahme wegen
|
|
Copyleft) — „Custody"-Feature, Kernaussage „know who has what at all times".
|
|
|
|
## ASSET-008 — Consumable
|
|
|
|
- **Ziel:** Verbrauchsmaterial als eigenes Konzept vom Einzelgerät abgrenzen.
|
|
- **Beschreibung:** Consumable-Typ mit Mengenführung statt Einzelinstanz-pro-Objekt-ID.
|
|
- **Benutzerwert:** Verbandsmaterial/Medikamente etc. sinnvoll ohne künstliche Einzel-IDs je
|
|
Stück verwalten.
|
|
- **Abhängigkeiten:** ASSET-002
|
|
- **Datenmodell:** `consumable` (asset_type_id, ...) — im Unterschied zu Asset keine 1:1
|
|
Objekt-ID pro Stück, sondern Menge an einem Ort (Ausbau folgt in INV-003)
|
|
- **Backend:** Grundmodell
|
|
- **Frontend:** Unterscheidung im AssetType-Formular („ist Verbrauchsmaterial")
|
|
- **Mobile:** Anzeige
|
|
- **QR-Code/Seriennummer:** Consumables i.d.R. ohne SN, ggf. Charge (INV-004)
|
|
- **Inventarnummer:** i.d.R. nicht je Stück, ggf. je Charge
|
|
- **Akte:** vereinfachte Akte (Bestandsverlauf statt Einzelverlauf)
|
|
- **Rechte:** Materialwart+
|
|
- **Audit:** Änderung geloggt
|
|
- **Akzeptanzkriterien:** Consumable-Typ anlegen, unterscheidet sich klar von Asset im
|
|
Datenmodell (keine Einzel-Instanzen entstehen).
|
|
- **Tests:** Abgrenzungstest.
|
|
- **DoD:** Grundlage für INV-003 gelegt.
|
|
|
|
## ASSET-009 — Nutzungszähler (Kilometer/Betriebsstunden generisch)
|
|
|
|
- **Nachtrag (Nutzer-Fund):** ursprünglich fälschlich als FLEET-003 fahrzeug-gebunden
|
|
geplant. Betriebsstunden brauchen aber auch Stromerzeuger, Pumpen und andere Geräte
|
|
(explizit in der Ursprungs-Anforderung Modul 14 „Wartung": „kilometerabhängige UND
|
|
betriebsstundenabhängige Wartung" — nicht auf Fahrzeuge beschränkt). Generischer
|
|
Nutzungszähler gehört daher ins Assets-Epic, nicht ins Fleet-Epic.
|
|
- **Ziel:** Nutzungsgrad JEDES Assets erfassen, das einen Zähler hat (Kilometer ODER
|
|
Betriebsstunden ODER beides) — Basis für zähler-abhängige Wartungsintervalle (MAINT-002).
|
|
- **Beschreibung:** generisches Zählerfeld je Asset (Typ: km/Betriebsstunden/keins),
|
|
Erfassungsverlauf (nicht nur aktueller Wert, sondern Verlauf der Meldungen).
|
|
- **Benutzerwert:** Fahrzeuge (km), aber auch Stromerzeuger/Pumpen/Kompressoren
|
|
(Betriebsstunden) bekommen dieselbe Wartungslogik, ohne dass jedes Modul sein eigenes
|
|
Zählerfeld neu erfindet.
|
|
- **Abhängigkeiten:** ASSET-003
|
|
- **Datenmodell:** `asset.zaehler_typ` (enum: keiner/kilometer/betriebsstunden),
|
|
`asset.zaehlerstand` (aktuell), optional `zaehlerstand_historie`
|
|
- **Backend:** Update-Endpoint mit Plausibilitätsprüfung (nur steigend, Override nur
|
|
Administrator)
|
|
- **Frontend:** Eingabefeld bei Kontrolle/Rückkehr bzw. nach Nutzung
|
|
- **Mobile:** Eingabe im Feld
|
|
- **QR-Code/Seriennummer/Inventarnummer:** nein
|
|
- **Akte:** Stammdatenbereich
|
|
- **Rechte:** jeder Nutzer darf melden, Korrektur nur Administrator
|
|
- **Audit:** Änderung geloggt
|
|
- **Akzeptanzkriterien:** Wert kann nur steigen (Validierung gegen Rückwärtslauf, außer
|
|
Admin-Override); funktioniert gleichermaßen für ein Fahrzeug (km) und ein Gerät
|
|
(Betriebsstunden).
|
|
- **Tests:** Validierungstest je Zählertyp, Test mit einem Nicht-Fahrzeug-Asset
|
|
(z.B. Stromerzeuger).
|
|
- **DoD:** mind. ein Fahrzeug UND ein Gerät (z.B. Stromerzeuger) nutzen denselben
|
|
Mechanismus nachweisbar.
|
|
|
|
---
|
|
|
|
**MABEA-Ist-Stand-Abgleich:** ASSET-001…004 entsprechen `Bereich`/`Kategorie`,
|
|
`Objekttyp`, `Objekt`, `ObjektStatus` — vollständig vorhanden, inkl. des 5-stufigen
|
|
Fahrzeug-Status als Beispiel für ASSET-004-Erweiterung. ASSET-005 (Suche/Filter) vorhanden
|
|
in ObjektListPage/ObjektSection. ASSET-006 (Bewegungshistorie) vorhanden als
|
|
`Lagerbewegung` (diente hier sogar als Vorbild). **ASSET-007 (AssetSet) und ASSET-008
|
|
(Consumable als eigenständiges Konzept) fehlen** — echte Lücken, wie schon in der
|
|
Gap-Analyse vorher notiert. **ASSET-009 (generischer Nutzungszähler) fehlt ebenfalls:**
|
|
MABEA hat Kilometerstand/Betriebsstunden nur an `fahrzeugdetails` (1:1 zu Objekt mit
|
|
`ist_zugfahrzeug`), Geräte wie Stromerzeuger/Pumpen (`GeraetInstanz`) haben aktuell KEIN
|
|
Betriebsstunden-Feld — echte Lücke, wenn Wartung künftig betriebsstundenabhängig geplant
|
|
werden soll (MAINT-002, Wartungs-Epic in MABEA ohnehin noch komplett offen).
|