Fix: Freigaberollen korrekt filtern und speichern
All checks were successful
CI / Build (push) Successful in 1m18s
CI / Deploy (push) Successful in 54s

- Korrigiere normalizeApprovalPermissions: verwende Set für korrekte Deduplizierung
- Füge getAvailableApprovalRoles hinzu, um basierend auf der Benutzerrolle
  die verfügbaren Freigaberollen zu bestimmen:
  - ADMIN (Vorstand): Vorstand A, Vorstand B
  - FINANCE (Finanz-AG): Finanz-AG
  - MEMBER (AG-Mitglied): Keine
- Aktualisiere renderApprovalPermissionSelector mit rollenbasierter Filterung
- Verhindere Auswahl inkompatibler Kombinationen (z.B. Vorstand A + B zusammen)
This commit is contained in:
MiniMax Agent
2026-04-14 06:06:39 +08:00
parent 44a2c3aeae
commit 5a8b0871a0
2 changed files with 50 additions and 20 deletions

View File

@@ -45,6 +45,7 @@ import {
approvalLabel,
canManageBudgets,
canManageUsers,
getAvailableApprovalRoles,
roleLabel
} from "@/lib/domain";
@@ -1091,7 +1092,8 @@ export function DashboardShell({
function renderApprovalPermissionSelector(
value: ApprovalPermissionValue[],
onToggle: (approvalType: ApprovalPermissionValue) => void,
helperText: string
helperText: string,
availableApprovalTypes: ApprovalPermissionValue[]
) {
return (
<Stack spacing={1}>
@@ -1099,21 +1101,27 @@ export function DashboardShell({
Freigaberollen
</Typography>
<Stack direction="row" gap={1} useFlexGap flexWrap="wrap">
{APPROVAL_FLOW.map((approvalType) => {
const selected = value.includes(approvalType);
{availableApprovalTypes.length > 0 ? (
availableApprovalTypes.map((approvalType) => {
const selected = value.includes(approvalType);
return (
<Button
key={approvalType}
type="button"
size="small"
variant={selected ? "contained" : "outlined"}
onClick={() => onToggle(approvalType)}
>
{approvalLabel(approvalType)}
</Button>
);
})}
return (
<Button
key={approvalType}
type="button"
size="small"
variant={selected ? "contained" : "outlined"}
onClick={() => onToggle(approvalType)}
>
{approvalLabel(approvalType)}
</Button>
);
})
) : (
<Typography variant="body2" color="text.secondary">
Keine Freigaberollen verfuegbar
</Typography>
)}
</Stack>
<Typography variant="body2" color="text.secondary">
{helperText}
@@ -1778,7 +1786,8 @@ export function DashboardShell({
...current,
approvalPermissions: toggleApprovalPermission(current.approvalPermissions, approvalType)
})),
"Lege fest, für welche Freigabeschritte dieses Konto zeichnen darf."
"Lege fest, für welche Freigabeschritte dieses Konto zeichnen darf.",
getAvailableApprovalRoles(userForm.role)
)}
<Button type="submit" variant="outlined" disabled={busy}>
Nutzer speichern
@@ -1970,7 +1979,8 @@ export function DashboardShell({
updateManagedUserDraft(user, {
approvalPermissions: toggleApprovalPermission(draft.approvalPermissions, approvalType)
}),
"Lege fest, welche Freigabeschritte dieses Konto autorisieren darf."
"Lege fest, welche Freigabeschritte dieses Konto autorisieren darf.",
getAvailableApprovalRoles(draft.role)
)}
<Stack direction="row" gap={1} useFlexGap flexWrap="wrap">
<Button type="button" variant="contained" disabled={busy} onClick={() => handleUpdateUser(user)}>

View File

@@ -97,6 +97,17 @@ export function canDeleteExpense(
return viewerId === creatorId && approvalStatus === "PENDING" && !paidAt && !documentedAt;
}
export function getAvailableApprovalRoles(role: AppRole): ApprovalTypeValue[] {
switch (role) {
case "ADMIN":
return ["CHAIR_A", "CHAIR_B"];
case "FINANCE":
return ["FINANCE"];
case "MEMBER":
return [];
}
}
export function normalizeApprovalPermissions(
_role: AppRole,
approvalPermissions: ApprovalTypeValue[] | null | undefined,
@@ -104,9 +115,18 @@ export function normalizeApprovalPermissions(
) {
const rawPermissions = approvalPermissions ?? (approvalPreference ? [approvalPreference] : []);
return APPROVAL_FLOW.filter(
(approvalType, index) => rawPermissions.includes(approvalType) && rawPermissions.indexOf(approvalType) === index
) as ApprovalTypeValue[];
// Deduplizierung: behalte jeden Eintrag nur beim ersten Vorkommen
const seen = new Set<ApprovalTypeValue>();
const unique: ApprovalTypeValue[] = [];
for (const perm of rawPermissions) {
if (!seen.has(perm)) {
seen.add(perm);
unique.push(perm);
}
}
// Sortiere nach der Reihenfolge in APPROVAL_FLOW
return APPROVAL_FLOW.filter((type) => unique.includes(type)) as ApprovalTypeValue[];
}
export function getLegacyApprovalPreference(approvalPermissions: ApprovalTypeValue[]) {