SIM-Karten: Feld "Kartennutzer" für Firmen-/Familienverträge

Bei Firmenverträgen (Vertragsinhaber = Firma, Nutzer = Mitarbeiter)
und Familienverträgen (Inhaber = Eltern, Nutzer = Kind) brauchten
wir ein Feld, das den tatsächlichen Nutzer der SIM-Karte erfasst.

Backend: SimCard.cardUser (String?, optional), Migration
20260601100000_sim_card_user mit IF NOT EXISTS. Im Service durch
Create + Update propagiert.

Frontend: Input "Kartennutzer" pro SIM-Karte in ContractForm
(eigene Zeile oberhalb der technischen Felder Rufnummer/SIM-Nr/
PIN/PUK). In ContractDetail wird der Nutzer als "Nutzer: <Name>"
neben den Hauptkarte/Multisim-Badges angezeigt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 08:10:16 +02:00
parent 9e3bce85f0
commit 4acfd9de1c
6 changed files with 42 additions and 1 deletions
@@ -134,9 +134,15 @@ function SimCardDisplay({ simCard }: { simCard: SimCard }) {
return (
<div className="p-3 bg-gray-50 rounded-lg border">
<div className="flex items-center gap-2 mb-2">
<div className="flex items-center gap-2 mb-2 flex-wrap">
{simCard.isMain && <Badge variant="success">Hauptkarte</Badge>}
{simCard.isMultisim && <Badge variant="warning">Multisim</Badge>}
{simCard.cardUser && (
<span className="text-sm text-gray-700">
<span className="text-gray-500">Nutzer:</span>{' '}
<span className="font-medium">{simCard.cardUser}</span>
</span>
)}
</div>
<dl className="grid grid-cols-2 md:grid-cols-4 gap-3 text-sm">
{simCard.phoneNumber && (
@@ -192,6 +192,7 @@ export default function ContractForm() {
hasExistingPuk?: boolean; // Zeigt an ob PUK bereits in DB vorhanden
isMultisim: boolean;
isMain: boolean;
cardUser: string;
}
const [simCards, setSimCards] = useState<SimCardInput[]>([]);
@@ -379,6 +380,7 @@ export default function ContractForm() {
hasExistingPuk: !!sc.puk, // true wenn verschlüsselter Wert vorhanden
isMultisim: sc.isMultisim,
isMain: sc.isMain,
cardUser: sc.cardUser || '',
})));
} else {
setSimCards([]);
@@ -610,6 +612,7 @@ export default function ContractForm() {
puk: sc.puk || undefined, // Passwort: undefined = nicht ändern
isMultisim: sc.isMultisim,
isMain: sc.isMain,
cardUser: emptyToNull(sc.cardUser),
})) : undefined,
};
}
@@ -1490,6 +1493,18 @@ export default function ContractForm() {
<Trash2 className="w-4 h-4 text-red-500" />
</Button>
</div>
<div className="mb-3">
<Input
label="Kartennutzer"
value={card.cardUser}
onChange={(e) => {
const updated = [...simCards];
updated[index].cardUser = e.target.value;
setSimCards(updated);
}}
placeholder="z.B. Mitarbeiter-/Kind-Name (optional, kann vom Vertragsinhaber abweichen)"
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
<Input
label="Rufnummer"
@@ -1578,6 +1593,7 @@ export default function ContractForm() {
puk: '',
isMultisim: false,
isMain: simCards.length === 0, // Erste Karte ist Hauptkarte
cardUser: '',
}]);
}}
>
+3
View File
@@ -557,6 +557,9 @@ export interface SimCard {
puk?: string; // verschlüsselt
isMultisim: boolean;
isMain: boolean;
// Tatsächlicher Nutzer der Karte (z.B. Mitarbeiter bei Firmenvertrag,
// Kind bei Eltern-Vertrag) optional, kann vom Vertragsinhaber abweichen.
cardUser?: string;
createdAt?: string;
updatedAt?: string;
}