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 city,
|
||||||
String email,
|
String email,
|
||||||
String phoneNumber,
|
String phoneNumber,
|
||||||
|
String accountHolder,
|
||||||
|
String bankName,
|
||||||
|
String iban,
|
||||||
|
String bic,
|
||||||
String passwordHash,
|
String passwordHash,
|
||||||
boolean active,
|
boolean active,
|
||||||
UserRole role,
|
UserRole role,
|
||||||
|
|||||||
@@ -436,6 +436,10 @@ public class CatalogService {
|
|||||||
adminManaged ? blankToNull(mutation.city()) : null,
|
adminManaged ? blankToNull(mutation.city()) : null,
|
||||||
normalizeEmail(mutation.email()),
|
normalizeEmail(mutation.email()),
|
||||||
adminManaged ? blankToNull(mutation.phoneNumber()) : null,
|
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()),
|
encodeIfPresent(mutation.password()),
|
||||||
mutation.active(),
|
mutation.active(),
|
||||||
adminManaged ? normalizeManagedRole(mutation.role()) : UserRole.CUSTOMER,
|
adminManaged ? normalizeManagedRole(mutation.role()) : UserRole.CUSTOMER,
|
||||||
@@ -467,6 +471,10 @@ public class CatalogService {
|
|||||||
isPrimaryUser(existing) || actor.role() == UserRole.ADMIN ? blankToNull(mutation.city()) : existing.city(),
|
isPrimaryUser(existing) || actor.role() == UserRole.ADMIN ? blankToNull(mutation.city()) : existing.city(),
|
||||||
normalizeEmail(mutation.email()),
|
normalizeEmail(mutation.email()),
|
||||||
isPrimaryUser(existing) || actor.role() == UserRole.ADMIN ? blankToNull(mutation.phoneNumber()) : existing.phoneNumber(),
|
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()),
|
isBlank(mutation.password()) ? existing.passwordHash() : passwordEncoder.encode(mutation.password()),
|
||||||
mutation.active(),
|
mutation.active(),
|
||||||
actor.role() == UserRole.ADMIN
|
actor.role() == UserRole.ADMIN
|
||||||
@@ -516,6 +524,10 @@ public class CatalogService {
|
|||||||
existing.city(),
|
existing.city(),
|
||||||
existing.email(),
|
existing.email(),
|
||||||
existing.phoneNumber(),
|
existing.phoneNumber(),
|
||||||
|
existing.accountHolder(),
|
||||||
|
existing.bankName(),
|
||||||
|
existing.iban(),
|
||||||
|
existing.bic(),
|
||||||
passwordEncoder.encode(newPassword),
|
passwordEncoder.encode(newPassword),
|
||||||
existing.active(),
|
existing.active(),
|
||||||
existing.role(),
|
existing.role(),
|
||||||
@@ -580,6 +592,10 @@ public class CatalogService {
|
|||||||
city,
|
city,
|
||||||
normalizedEmail,
|
normalizedEmail,
|
||||||
phoneNumber,
|
phoneNumber,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
passwordEncoder.encode(mutation.password()),
|
passwordEncoder.encode(mutation.password()),
|
||||||
false,
|
false,
|
||||||
UserRole.CUSTOMER,
|
UserRole.CUSTOMER,
|
||||||
@@ -600,6 +616,10 @@ public class CatalogService {
|
|||||||
created.city(),
|
created.city(),
|
||||||
created.email(),
|
created.email(),
|
||||||
created.phoneNumber(),
|
created.phoneNumber(),
|
||||||
|
created.accountHolder(),
|
||||||
|
created.bankName(),
|
||||||
|
created.iban(),
|
||||||
|
created.bic(),
|
||||||
created.passwordHash(),
|
created.passwordHash(),
|
||||||
false,
|
false,
|
||||||
created.role(),
|
created.role(),
|
||||||
@@ -708,6 +728,10 @@ public class CatalogService {
|
|||||||
user.city(),
|
user.city(),
|
||||||
user.email(),
|
user.email(),
|
||||||
user.phoneNumber(),
|
user.phoneNumber(),
|
||||||
|
user.accountHolder(),
|
||||||
|
user.bankName(),
|
||||||
|
user.iban(),
|
||||||
|
user.bic(),
|
||||||
user.active(),
|
user.active(),
|
||||||
normalizeStoredRole(user.role()),
|
normalizeStoredRole(user.role()),
|
||||||
user.updatedAt()
|
user.updatedAt()
|
||||||
@@ -743,6 +767,10 @@ public class CatalogService {
|
|||||||
user.city(),
|
user.city(),
|
||||||
user.email(),
|
user.email(),
|
||||||
user.phoneNumber(),
|
user.phoneNumber(),
|
||||||
|
user.accountHolder(),
|
||||||
|
user.bankName(),
|
||||||
|
user.iban(),
|
||||||
|
user.bic(),
|
||||||
normalizeStoredRole(user.role())
|
normalizeStoredRole(user.role())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -835,6 +863,10 @@ public class CatalogService {
|
|||||||
user.city(),
|
user.city(),
|
||||||
user.email(),
|
user.email(),
|
||||||
user.phoneNumber(),
|
user.phoneNumber(),
|
||||||
|
user.accountHolder(),
|
||||||
|
user.bankName(),
|
||||||
|
user.iban(),
|
||||||
|
user.bic(),
|
||||||
user.passwordHash(),
|
user.passwordHash(),
|
||||||
user.active(),
|
user.active(),
|
||||||
normalizeStoredRole(user.role()),
|
normalizeStoredRole(user.role()),
|
||||||
@@ -870,6 +902,10 @@ public class CatalogService {
|
|||||||
null,
|
null,
|
||||||
email,
|
email,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
passwordEncoder.encode(rawPassword),
|
passwordEncoder.encode(rawPassword),
|
||||||
true,
|
true,
|
||||||
role,
|
role,
|
||||||
@@ -997,6 +1033,10 @@ public class CatalogService {
|
|||||||
String city,
|
String city,
|
||||||
String email,
|
String email,
|
||||||
String phoneNumber,
|
String phoneNumber,
|
||||||
|
String accountHolder,
|
||||||
|
String bankName,
|
||||||
|
String iban,
|
||||||
|
String bic,
|
||||||
UserRole role
|
UserRole role
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
@@ -1066,6 +1106,10 @@ public class CatalogService {
|
|||||||
String city,
|
String city,
|
||||||
String email,
|
String email,
|
||||||
String phoneNumber,
|
String phoneNumber,
|
||||||
|
String accountHolder,
|
||||||
|
String bankName,
|
||||||
|
String iban,
|
||||||
|
String bic,
|
||||||
boolean active,
|
boolean active,
|
||||||
UserRole role,
|
UserRole role,
|
||||||
LocalDateTime updatedAt
|
LocalDateTime updatedAt
|
||||||
@@ -1083,6 +1127,10 @@ public class CatalogService {
|
|||||||
String city,
|
String city,
|
||||||
String email,
|
String email,
|
||||||
String phoneNumber,
|
String phoneNumber,
|
||||||
|
String accountHolder,
|
||||||
|
String bankName,
|
||||||
|
String iban,
|
||||||
|
String bic,
|
||||||
String password,
|
String password,
|
||||||
boolean active,
|
boolean active,
|
||||||
UserRole role
|
UserRole role
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ export interface UserOption {
|
|||||||
city: string | null;
|
city: string | null;
|
||||||
email: string | null;
|
email: string | null;
|
||||||
phoneNumber: string | null;
|
phoneNumber: string | null;
|
||||||
|
accountHolder: string | null;
|
||||||
|
bankName: string | null;
|
||||||
|
iban: string | null;
|
||||||
|
bic: string | null;
|
||||||
role: UserRole;
|
role: UserRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ export default function AdminProfilePage() {
|
|||||||
city: "",
|
city: "",
|
||||||
email: "",
|
email: "",
|
||||||
phoneNumber: "",
|
phoneNumber: "",
|
||||||
|
accountHolder: "",
|
||||||
|
bankName: "",
|
||||||
|
iban: "",
|
||||||
|
bic: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load current user data
|
// Load current user data
|
||||||
@@ -36,6 +40,10 @@ export default function AdminProfilePage() {
|
|||||||
city: currentUser.city || "",
|
city: currentUser.city || "",
|
||||||
email: currentUser.email || "",
|
email: currentUser.email || "",
|
||||||
phoneNumber: currentUser.phoneNumber || "",
|
phoneNumber: currentUser.phoneNumber || "",
|
||||||
|
accountHolder: currentUser.accountHolder || "",
|
||||||
|
bankName: currentUser.bankName || "",
|
||||||
|
iban: currentUser.iban || "",
|
||||||
|
bic: currentUser.bic || "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -77,6 +85,10 @@ export default function AdminProfilePage() {
|
|||||||
city: formData.city.trim() || null,
|
city: formData.city.trim() || null,
|
||||||
email: formData.email.trim(),
|
email: formData.email.trim(),
|
||||||
phoneNumber: formData.phoneNumber.trim() || null,
|
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,
|
active: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -92,6 +104,10 @@ export default function AdminProfilePage() {
|
|||||||
city: response.city,
|
city: response.city,
|
||||||
email: response.email,
|
email: response.email,
|
||||||
phoneNumber: response.phoneNumber,
|
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>
|
<p className="eyebrow">Stammdaten</p>
|
||||||
<h3>Meine Stammdaten</h3>
|
<h3>Meine Stammdaten</h3>
|
||||||
<p className="muted-text">
|
<p className="muted-text">
|
||||||
Verwalten Sie hier Ihre persönlichen und Unternehmensdaten.
|
Verwalten Sie hier Ihre persönlichen, Unternehmens- und Bankdaten.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -140,12 +156,12 @@ export default function AdminProfilePage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Stammdaten-Formular */}
|
{/* Persönliche Daten */}
|
||||||
<section className="section-card">
|
<section className="section-card">
|
||||||
<div className="section-card__header">
|
<div className="section-card__header">
|
||||||
<div>
|
<div>
|
||||||
<p className="eyebrow">Profil</p>
|
<p className="eyebrow">Profil</p>
|
||||||
<h3>Stammdaten bearbeiten</h3>
|
<h3>Persönliche Daten</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -255,17 +271,82 @@ export default function AdminProfilePage() {
|
|||||||
disabled={saving}
|
disabled={saving}
|
||||||
/>
|
/>
|
||||||
</label>
|
</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
|
<button
|
||||||
type="submit"
|
type="button"
|
||||||
className="accent-button"
|
className="accent-button"
|
||||||
|
onClick={handleSubmit}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
>
|
>
|
||||||
{saving ? "Wird gespeichert..." : "Stammdaten speichern"}
|
{saving ? "Wird gespeichert..." : "Stammdaten speichern"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Info-Box */}
|
{/* Info-Box */}
|
||||||
|
|||||||
Reference in New Issue
Block a user