feat(helpdesk): add Software Products page with BC contract type sync

Add a new Software-Produkte feature to the helpdesk module that syncs
contract types (Create_SaaS_License=true) from BC OData into a local
database table with a nightly scheduler job, providing a Grid.js list
page and detail/edit page for managing custom product names.

- DB migration 003: helpdesk_software_products table (code UNIQUE key)
- BcODataGateway: FS_Contract_Types entity with SaaS filter + fallback
- SoftwareProductRepository: upsert, listPaged, softDelete, updateName
- SoftwareProductSyncService: fetch → upsert → soft-delete lifecycle
- SoftwareProductSyncJobHandler: daily at 02:00 via scheduler platform
- SoftwareProductService: web UI business logic with validation
- Permission: helpdesk.software-products.manage (nav-gated)
- List page: Grid.js with Code, BC Description, Name, Status columns
- Detail page: Code/BC Description read-only, Name editable, PRG pattern
- i18n: de + en translation keys

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-14 22:16:21 +02:00
parent d472026df4
commit ef4473de64
23 changed files with 1209 additions and 5 deletions

View File

@@ -356,5 +356,24 @@
"Lookup": "Nachschlagen",
"Monitoring": "Monitoring",
"Contract type": "Vertragsart",
"Customer": "Kunde"
"Customer": "Kunde",
"Software products": "Software-Produkte",
"Software product": "Software-Produkt",
"Search software products...": "Software-Produkte suchen...",
"BC description": "BC-Bezeichnung",
"Product name": "Produktname",
"Code": "Code",
"Active": "Aktiv",
"Inactive": "Inaktiv",
"Last synced": "Zuletzt synchronisiert",
"Modified": "Geändert",
"Edit software product": "Software-Produkt bearbeiten",
"Back to list": "Zurück zur Liste",
"Save & close": "Speichern & schließen",
"Software product updated": "Software-Produkt aktualisiert",
"Software product not found": "Software-Produkt nicht gefunden",
"Product details": "Produktdetails",
"Enter product name...": "Produktname eingeben...",
"Name must not exceed 255 characters": "Name darf maximal 255 Zeichen lang sein",
"Failed to save": "Speichern fehlgeschlagen"
}