feat: import users` real names from bpn API

This commit is contained in:
Björn Fromme
2026-08-17 14:24:56 +02:00
parent bf69fcceff
commit 77de1643f0
11 changed files with 96 additions and 7 deletions
@@ -129,7 +129,13 @@ class PersonalDataController extends AbstractController
// Update profile completeness flag on user entity
$isComplete = $this->completenessChecker->isComplete($personalData);
$user->setProfileComplete($isComplete);
$user
->setProfileComplete($isComplete)
// Otherwise a rename here would stay invisible in the backend until the next
// login, which is the only other place the name is synced from BPN.
->setFirstName($personalData->firstName)
->setLastName($personalData->name)
;
$this->entityManager->flush();
$this->addFlash('success', 'Deine persönlichen Daten wurden aktualisiert');
+46
View File
@@ -27,6 +27,12 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[ORM\Column(type: 'integer', nullable: true)]
private ?int $addressId = null;
#[ORM\Column(type: 'string', length: 100, nullable: true)]
private ?string $firstName = null;
#[ORM\Column(type: 'string', length: 100, nullable: true)]
private ?string $lastName = null;
/**
* @var array<string>
*/
@@ -91,6 +97,46 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(?string $firstName): static
{
$this->firstName = $firstName;
return $this;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(?string $lastName): static
{
$this->lastName = $lastName;
return $this;
}
public function getFullName(): ?string
{
$fullName = trim(sprintf('%s %s', $this->firstName, $this->lastName));
return '' !== $fullName ? $fullName : null;
}
/**
* The name to identify this account by in the UI. BusPro only fills the name in on login, so
* accounts that have not signed in since the columns were added fall back to their e-mail.
*/
public function getDisplayName(): string
{
return $this->getFullName() ?? (string) $this->email;
}
public function getPassword(): ?string
{
return base64_decode($this->password);
@@ -57,7 +57,7 @@ final readonly class AccommodationBookingFilterOptionsProvider
$managers[(int) $manager->getId()] = $manager;
}
uasort($managers, static fn (User $a, User $b) => strcasecmp((string) $a->getEmail(), (string) $b->getEmail()));
uasort($managers, static fn (User $a, User $b) => strcasecmp($a->getDisplayName(), $b->getDisplayName()));
return array_values($managers);
}
@@ -63,7 +63,7 @@ class AccommodationBookingFilterType extends AbstractListFilterType
'label' => 'Betreuer:in',
'class' => User::class,
'choices' => $options['managers'],
'choice_label' => 'email',
'choice_label' => 'displayName',
'placeholder' => 'alle',
'required' => false,
]];
@@ -130,7 +130,7 @@ class AccommodationBookingType extends AbstractType
'class' => User::class,
'required' => false,
'choices' => $options['assignable_managers'],
'choice_label' => 'email',
'choice_label' => 'displayName',
'placeholder' => 'keine Zuordnung',
'label' => 'Bearbeiter:in',
]);
@@ -81,7 +81,7 @@ class AccommodationBookingFilterDto extends AbstractListFilterDto
} elseif (null !== $this->managedBy) {
$chips[] = new ListFilterChip(
'Betreuer:in',
(string) $this->managedBy->getEmail(),
$this->managedBy->getDisplayName(),
$this->managedByLocked ? [] : ['managedBy'],
);
}
+2
View File
@@ -29,6 +29,8 @@ class UserRepository extends ServiceEntityRepository
$this->applySearchTerm($qb, $filter->searchTerm(), [
'user.email',
'user.firstName',
'user.lastName',
'user.addressId',
'user.personId',
]);
+2
View File
@@ -119,6 +119,8 @@ class BpnAuthenticator extends AbstractLoginFormAuthenticator implements Authent
->setPassword($encryptedPassword)
->setPersonId($personalData->personId)
->setAddressId($personalData->addressId)
->setFirstName($personalData->firstName)
->setLastName($personalData->name)
->setLastLoginAt(new \DateTimeImmutable())
->setProfileComplete($this->completenessChecker->isComplete($personalData))
;