feat(buchhaltung): budget types, erstattungen, recurring tab move, overview dividers, order completion guard

This commit is contained in:
Matthias Hochmeister
2026-03-30 14:07:04 +02:00
parent 13aa4be599
commit b21abce9e3
10 changed files with 615 additions and 140 deletions

View File

@@ -1,5 +1,6 @@
import React, { useState, useRef } from 'react';
import {
Alert,
Box,
Typography,
Paper,
@@ -205,6 +206,7 @@ export default function BestellungDetail() {
const canApprove = hasPermission('bestellungen:approve');
const canExport = hasPermission('bestellungen:export');
const validTransitions = bestellung ? STATUS_TRANSITIONS[bestellung.status] : [];
const allCostsEntered = positionen.length === 0 || positionen.every(p => p.einzelpreis != null && Number(p.einzelpreis) > 0);
// All statuses except current, for force override
const ALL_STATUSES: BestellungStatus[] = ['entwurf', 'wartet_auf_genehmigung', 'bereit_zur_bestellung', 'bestellt', 'teillieferung', 'lieferung_pruefen', 'abgeschlossen'];
@@ -766,7 +768,11 @@ export default function BestellungDetail() {
{/* ── Status Action ── */}
{(canManageOrders || canCreate || canApprove) && (
<Box sx={{ mb: 3, display: 'flex', gap: 1, alignItems: 'center' }}>
<Box sx={{ mb: 3 }}>
{validTransitions.includes('abgeschlossen' as BestellungStatus) && !allCostsEntered && (
<Alert severity="warning" sx={{ mb: 2 }}>Nicht alle Positionen haben Kosten. Bitte Einzelpreise eintragen, bevor die Bestellung abgeschlossen wird.</Alert>
)}
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>
{validTransitions
.filter((s) => {
// Approve/reject transitions from wartet_auf_genehmigung require canApprove
@@ -787,11 +793,13 @@ export default function BestellungDetail() {
? 'Ablehnen'
: `Status: ${BESTELLUNG_STATUS_LABELS[s]}`;
const color = isApprove ? 'success' : isReject ? 'error' : 'primary';
const isAbgeschlossen = s === 'abgeschlossen';
return (
<Button
key={s}
variant="contained"
color={color as 'success' | 'error' | 'primary'}
disabled={isAbgeschlossen && !allCostsEntered}
onClick={() => { setStatusForce(false); setStatusConfirmTarget(s); }}
>
{label}
@@ -830,6 +838,7 @@ export default function BestellungDetail() {
</Menu>
</>
)}
</Box>
</Box>
)}