Gutschriften Phase 2b: Vertrags-UI + Beleg-Upload + Nummernkreis-Seite

Frontend:
- CreditNotesSection im Vertragsdetail (eigene Section wie Rechnungen):
  Liste + Anlegen/Bearbeiten (Modal). Geld/Sachwert mit passenden
  Feldern, USt-Block mit Live-Vorschau Netto/USt/Brutto, Datum, Ort,
  Unterschrift, 'Ware erhalten'. Loeschen mit Bestaetigung.
- Ueberweisungsbeleg-Upload/-Anzeige/-Entfernen (nur Geld-Gutschriften).
- Nummernkreis-Verwaltung als Settings-Seite mit Live-Vorschau der
  naechsten Nummer.
- Frontend-Typen (CreditNote etc.) + creditNoteApi.

Backend:
- Ueberweisungsbeleg-Upload-Route /upload/credit-notes/:id/receipt
  (+ DELETE), Portal geblockt, Ownership ueber Vertrag.
- fileDownload: Ownership-Aufloesung fuer credit-note-receipts +
  credit-notes (Vertrag) ergaenzt.

Als Section statt Tab-Balken, weil die Vertragsansicht kartenbasiert
ist (kein bestehender Tab-Balken); spaeter umbaubar.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-06 13:15:02 +02:00
co-authored by Claude Opus 4.8
parent 3580c51cb1
commit 9e38cb32f0
10 changed files with 804 additions and 6 deletions
@@ -6,6 +6,7 @@ import { contractApi, uploadApi, meterApi, contractTaskApi, appSettingsApi, gdpr
import { ContractEmailsSection } from '../../components/email';
import { ContractDetailModal, ContractHistorySection } from '../../components/contracts';
import InvoicesSection from '../../components/contracts/InvoicesSection';
import CreditNotesSection from '../../components/contracts/CreditNotesSection';
import CustomerInfoModal from '../../components/contracts/CustomerInfoModal';
import { useAuth } from '../../context/AuthContext';
import Card from '../../components/ui/Card';
@@ -3325,6 +3326,14 @@ export default function ContractDetail() {
</Card>
)}
{/* Gutschriften (Subventionen) nur Mitarbeiter/Admin */}
{!isCustomerPortal && hasPermission('contracts:read') && (
<CreditNotesSection
contractId={contractId}
canEdit={hasPermission('contracts:update')}
/>
)}
{/* Vertragsdokumente */}
{!isCustomerPortal && (
<ContractDocumentsSection