FDISK sync:
- fix(sync): strip 'KFZ-Führerschein / ' prefix from license class select option text before whitelist validation
- fix(sync): fix navigateAndGetTableRows to pick date column with most matches (prevents sidebar tables from hijacking dateColIdx for Beförderungen)
- fix(sync): input.value fallback now falls through to textContent when value is empty
- feat(sync): expand Ausbildungen to capture Kursnummer, Kurz, Kurs (full name), Erfolgscode from FDISK table; add migration 086
External orders (Bestellungen):
- fix(bestellungen): allow erhalten_menge editing in lieferung_pruefen status (resolves deadlock preventing order completion)
- fix(bestellungen): show cost/received warnings for bestellt/teillieferung/lieferung_pruefen, not just when abgeschlossen is next
- feat(bestellungen): rename status labels to Eingereicht, Genehmigt, Teilweise geliefert, Vollständig geliefert
- fix(bestellungen): remove duplicate Bestelldatum from PDF export
- feat(bestellungen): add catalog item autocomplete to creation form (auto-fills bezeichnung + artikelnummer)
Internal orders (Ausruestungsanfrage):
- fix(ausruestung): untracked items with zuweisung_typ='keine' now appear in Nicht-zugewiesen tab (frontend filter was too strict)
- feat(ausruestung): load user-specific personal items when ordering for another user
- feat(ausruestung): auto-set ist_ersatz=true for items from personal equipment list; add toggle for catalog/free-text items
- feat(ausruestung): load item eigenschaften when personal item with artikel_id is checked
Ausbildungen display:
- feat(mitglieder): show kursname (full), kurs_kurzbezeichnung chip, erfolgscode chip (color-coded) per Ausbildung entry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previous failed runs committed the CREATE TABLE/TRIGGER DDL outside a
transaction (pool.query BEGIN/ROLLBACK is not connection-pinned), leaving
the trigger in place. Re-runs then fail with 'already exists'.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Migration 084: new persoenliche_ausruestung table with catalog link, user
assignment, soft delete; adds zuweisung_typ/ausruestung_id/persoenlich_id
columns to ausruestung_anfrage_positionen; seeds feature group + 5 permissions
- Fix user data purge: table was shop_anfragen, renamed to ausruestung_anfragen
in mig 046 — caused full transaction rollback. Also keep mitglieder_profile
row but NULL FDISK-synced fields (dienstgrad, geburtsdatum, etc.) instead of
deleting the profile
- Personal equipment CRUD: backend service/controller/routes at
/api/persoenliche-ausruestung; frontend page with DataTable, user filter,
catalog Autocomplete, FAB create dialog; widget in Status group; sidebar
entry (Checkroom icon); card in MitgliedDetail Tab 0
- Ausruestungsanfrage item assignment: when a request reaches erledigt,
auto-opens ItemAssignmentDialog listing all delivered positions; each item
can be assigned as general equipment (vehicle/storage), personal item (user,
prefilled with requester), or not tracked; POST /requests/:id/assign backend
- StatCard refactored to use WidgetCard as outer shell for consistent header
styling across all dashboard widget templates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin can purge all personal data for a user (POST /api/admin/users/:userId/purge-data)
while keeping the account; clears profile, notifications, bookings, ical tokens, preferences
- Add isNewUser flag to auth callback response; first-login dialog prompts for Standesbuchnummer
- Add PageBreadcrumbs component and apply to 18 sub-pages across the app
- Cascade budget_typ changes from parent pot to all children recursively, converting amounts
(detailliert→einfach: sum into budget_gesamt; einfach→detailliert: zero all for redistribution)
- Migrate NextcloudTalkWidget to use shared WidgetCard template for consistent header styling
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>