toggleMandate(mandate.id)}
- >
-
- {expandedMandates.has(mandate.id) ?
:
}
-
{mandate.label || mandate.name}
-
- {mandate.featureInstances.length} Feature-Instanz(en)
-
+ {overview.mandates.map((mandate) => {
+ const mandateRoles = _resolveRoles(mandate.roleIds);
+
+ return (
+
+
toggleMandate(mandate.id)}>
+
+ {expandedMandates.has(mandate.id) ? (
+
+ ) : (
+
+ )}
+ {_mandateNameLine(mandate)}
+
+ {mandateRoles.length} Mandantenrolle(n) · {mandate.featureInstances.length} Feature-Instanz(en)
+
+
+ {expandedMandates.has(mandate.id) && (
+
+ {mandateRoles.length === 0 ? (
+
Keine Rollen direkt am Mandanten.
+ ) : (
+
+ {mandateRoles.map((r) => (
+ -
+ {r.roleLabel}
+
+ {r.scope}
+
+
+ ))}
+
+ )}
+
+
Feature-Instanzen
+ {mandate.featureInstances.length === 0 ? (
+
Keine Feature-Instanzen zugewiesen.
+ ) : (
+
+ {mandate.featureInstances.map((instance) => {
+ const instanceRoles = _resolveRoles(instance.roleIds);
+ const featureTitle = instance.featureLabel?.de || instance.featureCode;
+ return (
+
+
+ {instance.label}{' '}
+ ({featureTitle})
+
+ {instanceRoles.length === 0 ? (
+
+ Keine Rollen.
+
+ ) : (
+
+ {instanceRoles.map((r) => (
+ -
+ {r.roleLabel}
+
+ {r.scope}
+
+
+ ))}
+
+ )}
+
+ );
+ })}
+
+ )}
+
+ )}
- {expandedMandates.has(mandate.id) && (
-
- {mandate.featureInstances.length === 0 ? (
-
Keine Feature-Instanzen zugewiesen.
- ) : (
-
- {mandate.featureInstances.map(instance => (
-
-
- {instance.label}
-
-
- Feature: {instance.featureLabel?.de || instance.featureCode}
-
-
- Rollen: {instance.roleIds.length > 0
- ? overview.roles
- .filter(r => instance.roleIds.includes(r.id))
- .map(r => r.roleLabel)
- .join(', ')
- : 'Keine'
- }
-
-
- ))}
-
- )}
-
- )}
-
- ))}
+ );
+ })}
Keine Rollen zugewiesen.
- {overview.roles.map(role => (
-
-
toggleRole(role.id)}
- >
-
- {expandedRoles.has(role.id) ? : }
- {role.roleLabel}
-
- {role.scope}
-
-
-
- {expandedRoles.has(role.id) && (
-
-
-
Beschreibung: {role.description?.de || role.description?.en || '-'}
-
Quelle: {role.source === 'mandate'
- ? `Mandate: ${role.sourceMandateName}`
- : `Feature-Instanz: ${role.sourceInstanceLabel}`
- }
+ {globalRoles.length > 0 && (
+ <>
+
+ Globale Rollen
+
+
+ Nicht an einen Mandanten gebunden.
+
+
+ {globalRoles.map((role) => (
+
+
toggleRole(role.id)}>
+
+ {expandedRoles.has(role.id) ? (
+
+ ) : (
+
+ )}
+ {role.roleLabel}
+
+ {role.scope}
+
- )}
-
- ))}
-
+ {expandedRoles.has(role.id) && (
+
+
+
+ Beschreibung: {_roleDescriptionLine(role) || '—'}
+
+
+
+ )}
+
+ ))}
+
+ >
)}
);
diff --git a/src/pages/admin/wizards/AdminInvitationWizardPage.tsx b/src/pages/admin/wizards/AdminInvitationWizardPage.tsx
index 79fe0a5..fffc5b5 100644
--- a/src/pages/admin/wizards/AdminInvitationWizardPage.tsx
+++ b/src/pages/admin/wizards/AdminInvitationWizardPage.tsx
@@ -128,9 +128,8 @@ export const AdminInvitationWizardPage: React.FC = () => {
useEffect(() => {
if (inviteType === 'featureInstance' && selectedMandate) {
- fetchInstances(selectedMandate.id).then(data =>
- setInstances((data || []).filter((i: FeatureInstance) => i.enabled))
- );
+ // Show all instances for the mandate (including disabled). Previously only `enabled` instances were listed, which hid deactivated instances from admins.
+ fetchInstances(selectedMandate.id).then(data => setInstances(data || []));
} else {
setInstances([]);
setSelectedInstance(null);
@@ -411,7 +410,7 @@ export const AdminInvitationWizardPage: React.FC = () => {
{instances.length === 0 ? (
-
Keine aktiven Feature-Instanzen für diesen Mandanten vorhanden.
+
Keine Feature-Instanzen für diesen Mandanten vorhanden.
) : (
)}
diff --git a/src/pages/billing/BillingDataView.tsx b/src/pages/billing/BillingDataView.tsx
index 1d2571f..feb44f1 100644
--- a/src/pages/billing/BillingDataView.tsx
+++ b/src/pages/billing/BillingDataView.tsx
@@ -65,8 +65,9 @@ const BalanceCard: React.FC
= ({ balance, onCheckout, checkout
return 'Prepaid (Mandant)';
};
- const canTopUp = balance.billingModel === 'PREPAY_USER'
- || balance.billingModel === 'PREPAY_MANDATE';
+ // Stripe top-up on this page: only personal prepaid wallets. Mandate pool (PREPAY_MANDATE) is topped up by mandate admins via Administration → Billing.
+ const canStripeTopUpHere = balance.billingModel === 'PREPAY_USER';
+ const isMandatePrepaidPool = balance.billingModel === 'PREPAY_MANDATE';
return (
@@ -82,7 +83,20 @@ const BalanceCard: React.FC = ({ balance, onCheckout, checkout
Niedriges Guthaben
)}
- {canTopUp && onCheckout && (
+ {isMandatePrepaidPool && (
+
+ Aufladung des Mandanten-Guthabens ist nur für Mandanten-Administratoren möglich (Menü Administration → Billing).
+
+ )}
+ {canStripeTopUpHere && onCheckout && (
{!showCheckout ? (