feat: Add bank account details to admin profile
- Add accountHolder, bankName, iban, bic fields to AppUser domain - Update UserOption, UserRow, UserMutation records in CatalogService - Update all AppUser constructor calls to include new fields - Add bank fields to frontend UserOption and UserRow types - Add bank account form section to AdminProfilePage
This commit is contained in:
@@ -19,6 +19,10 @@ public record AppUser(
|
||||
String city,
|
||||
String email,
|
||||
String phoneNumber,
|
||||
String accountHolder,
|
||||
String bankName,
|
||||
String iban,
|
||||
String bic,
|
||||
String passwordHash,
|
||||
boolean active,
|
||||
UserRole role,
|
||||
|
||||
@@ -436,6 +436,10 @@ public class CatalogService {
|
||||
adminManaged ? blankToNull(mutation.city()) : null,
|
||||
normalizeEmail(mutation.email()),
|
||||
adminManaged ? blankToNull(mutation.phoneNumber()) : null,
|
||||
adminManaged ? blankToNull(mutation.accountHolder()) : null,
|
||||
adminManaged ? blankToNull(mutation.bankName()) : null,
|
||||
adminManaged ? blankToNull(mutation.iban()) : null,
|
||||
adminManaged ? blankToNull(mutation.bic()) : null,
|
||||
encodeIfPresent(mutation.password()),
|
||||
mutation.active(),
|
||||
adminManaged ? normalizeManagedRole(mutation.role()) : UserRole.CUSTOMER,
|
||||
@@ -467,6 +471,10 @@ public class CatalogService {
|
||||
isPrimaryUser(existing) || actor.role() == UserRole.ADMIN ? blankToNull(mutation.city()) : existing.city(),
|
||||
normalizeEmail(mutation.email()),
|
||||
isPrimaryUser(existing) || actor.role() == UserRole.ADMIN ? blankToNull(mutation.phoneNumber()) : existing.phoneNumber(),
|
||||
isPrimaryUser(existing) || actor.role() == UserRole.ADMIN ? blankToNull(mutation.accountHolder()) : existing.accountHolder(),
|
||||
isPrimaryUser(existing) || actor.role() == UserRole.ADMIN ? blankToNull(mutation.bankName()) : existing.bankName(),
|
||||
isPrimaryUser(existing) || actor.role() == UserRole.ADMIN ? blankToNull(mutation.iban()) : existing.iban(),
|
||||
isPrimaryUser(existing) || actor.role() == UserRole.ADMIN ? blankToNull(mutation.bic()) : existing.bic(),
|
||||
isBlank(mutation.password()) ? existing.passwordHash() : passwordEncoder.encode(mutation.password()),
|
||||
mutation.active(),
|
||||
actor.role() == UserRole.ADMIN
|
||||
@@ -516,6 +524,10 @@ public class CatalogService {
|
||||
existing.city(),
|
||||
existing.email(),
|
||||
existing.phoneNumber(),
|
||||
existing.accountHolder(),
|
||||
existing.bankName(),
|
||||
existing.iban(),
|
||||
existing.bic(),
|
||||
passwordEncoder.encode(newPassword),
|
||||
existing.active(),
|
||||
existing.role(),
|
||||
@@ -580,6 +592,10 @@ public class CatalogService {
|
||||
city,
|
||||
normalizedEmail,
|
||||
phoneNumber,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
passwordEncoder.encode(mutation.password()),
|
||||
false,
|
||||
UserRole.CUSTOMER,
|
||||
@@ -600,6 +616,10 @@ public class CatalogService {
|
||||
created.city(),
|
||||
created.email(),
|
||||
created.phoneNumber(),
|
||||
created.accountHolder(),
|
||||
created.bankName(),
|
||||
created.iban(),
|
||||
created.bic(),
|
||||
created.passwordHash(),
|
||||
false,
|
||||
created.role(),
|
||||
@@ -708,6 +728,10 @@ public class CatalogService {
|
||||
user.city(),
|
||||
user.email(),
|
||||
user.phoneNumber(),
|
||||
user.accountHolder(),
|
||||
user.bankName(),
|
||||
user.iban(),
|
||||
user.bic(),
|
||||
user.active(),
|
||||
normalizeStoredRole(user.role()),
|
||||
user.updatedAt()
|
||||
@@ -743,6 +767,10 @@ public class CatalogService {
|
||||
user.city(),
|
||||
user.email(),
|
||||
user.phoneNumber(),
|
||||
user.accountHolder(),
|
||||
user.bankName(),
|
||||
user.iban(),
|
||||
user.bic(),
|
||||
normalizeStoredRole(user.role())
|
||||
);
|
||||
}
|
||||
@@ -835,6 +863,10 @@ public class CatalogService {
|
||||
user.city(),
|
||||
user.email(),
|
||||
user.phoneNumber(),
|
||||
user.accountHolder(),
|
||||
user.bankName(),
|
||||
user.iban(),
|
||||
user.bic(),
|
||||
user.passwordHash(),
|
||||
user.active(),
|
||||
normalizeStoredRole(user.role()),
|
||||
@@ -870,6 +902,10 @@ public class CatalogService {
|
||||
null,
|
||||
email,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
passwordEncoder.encode(rawPassword),
|
||||
true,
|
||||
role,
|
||||
@@ -997,6 +1033,10 @@ public class CatalogService {
|
||||
String city,
|
||||
String email,
|
||||
String phoneNumber,
|
||||
String accountHolder,
|
||||
String bankName,
|
||||
String iban,
|
||||
String bic,
|
||||
UserRole role
|
||||
) {
|
||||
}
|
||||
@@ -1066,6 +1106,10 @@ public class CatalogService {
|
||||
String city,
|
||||
String email,
|
||||
String phoneNumber,
|
||||
String accountHolder,
|
||||
String bankName,
|
||||
String iban,
|
||||
String bic,
|
||||
boolean active,
|
||||
UserRole role,
|
||||
LocalDateTime updatedAt
|
||||
@@ -1083,6 +1127,10 @@ public class CatalogService {
|
||||
String city,
|
||||
String email,
|
||||
String phoneNumber,
|
||||
String accountHolder,
|
||||
String bankName,
|
||||
String iban,
|
||||
String bic,
|
||||
String password,
|
||||
boolean active,
|
||||
UserRole role
|
||||
|
||||
@@ -62,6 +62,10 @@ export interface UserOption {
|
||||
city: string | null;
|
||||
email: string | null;
|
||||
phoneNumber: string | null;
|
||||
accountHolder: string | null;
|
||||
bankName: string | null;
|
||||
iban: string | null;
|
||||
bic: string | null;
|
||||
role: UserRole;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ export default function AdminProfilePage() {
|
||||
city: "",
|
||||
email: "",
|
||||
phoneNumber: "",
|
||||
accountHolder: "",
|
||||
bankName: "",
|
||||
iban: "",
|
||||
bic: "",
|
||||
});
|
||||
|
||||
// Load current user data
|
||||
@@ -36,6 +40,10 @@ export default function AdminProfilePage() {
|
||||
city: currentUser.city || "",
|
||||
email: currentUser.email || "",
|
||||
phoneNumber: currentUser.phoneNumber || "",
|
||||
accountHolder: currentUser.accountHolder || "",
|
||||
bankName: currentUser.bankName || "",
|
||||
iban: currentUser.iban || "",
|
||||
bic: currentUser.bic || "",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -77,6 +85,10 @@ export default function AdminProfilePage() {
|
||||
city: formData.city.trim() || null,
|
||||
email: formData.email.trim(),
|
||||
phoneNumber: formData.phoneNumber.trim() || null,
|
||||
accountHolder: formData.accountHolder.trim() || null,
|
||||
bankName: formData.bankName.trim() || null,
|
||||
iban: formData.iban.trim() || null,
|
||||
bic: formData.bic.trim() || null,
|
||||
active: true,
|
||||
});
|
||||
|
||||
@@ -92,6 +104,10 @@ export default function AdminProfilePage() {
|
||||
city: response.city,
|
||||
email: response.email,
|
||||
phoneNumber: response.phoneNumber,
|
||||
accountHolder: response.accountHolder,
|
||||
bankName: response.bankName,
|
||||
iban: response.iban,
|
||||
bic: response.bic,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -122,7 +138,7 @@ export default function AdminProfilePage() {
|
||||
<p className="eyebrow">Stammdaten</p>
|
||||
<h3>Meine Stammdaten</h3>
|
||||
<p className="muted-text">
|
||||
Verwalten Sie hier Ihre persönlichen und Unternehmensdaten.
|
||||
Verwalten Sie hier Ihre persönlichen, Unternehmens- und Bankdaten.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
@@ -140,12 +156,12 @@ export default function AdminProfilePage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Stammdaten-Formular */}
|
||||
{/* Persönliche Daten */}
|
||||
<section className="section-card">
|
||||
<div className="section-card__header">
|
||||
<div>
|
||||
<p className="eyebrow">Profil</p>
|
||||
<h3>Stammdaten bearbeiten</h3>
|
||||
<h3>Persönliche Daten</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -255,17 +271,82 @@ export default function AdminProfilePage() {
|
||||
disabled={saving}
|
||||
/>
|
||||
</label>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<div className="field" style={{ gridColumn: "1 / -1" }}>
|
||||
{/* Bankverbindung */}
|
||||
<section className="section-card">
|
||||
<div className="section-card__header">
|
||||
<div>
|
||||
<p className="eyebrow">Zahlung</p>
|
||||
<h3>Bankverbindung</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field-grid field-grid--2col">
|
||||
<label className="field">
|
||||
<span>Kontoinhaber</span>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.accountHolder}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, accountHolder: e.target.value })
|
||||
}
|
||||
placeholder="Name des Kontoinhabers"
|
||||
disabled={saving}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="field">
|
||||
<span>Bankname</span>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.bankName}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, bankName: e.target.value })
|
||||
}
|
||||
placeholder="Name der Bank"
|
||||
disabled={saving}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="field">
|
||||
<span>IBAN</span>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.iban}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, iban: e.target.value })
|
||||
}
|
||||
placeholder="DE12 3456 7890 1234 5678 90"
|
||||
disabled={saving}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="field">
|
||||
<span>BIC</span>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.bic}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, bic: e.target.value })
|
||||
}
|
||||
placeholder="ABCDEFGHXXX"
|
||||
disabled={saving}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="field" style={{ marginTop: "1rem" }}>
|
||||
<button
|
||||
type="submit"
|
||||
type="button"
|
||||
className="accent-button"
|
||||
onClick={handleSubmit}
|
||||
disabled={saving}
|
||||
>
|
||||
{saving ? "Wird gespeichert..." : "Stammdaten speichern"}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
{/* Info-Box */}
|
||||
|
||||
Reference in New Issue
Block a user