From 828b9c8b4aa61272b35d67666b72474589b93d3b Mon Sep 17 00:00:00 2001 From: Kevin Papst Date: Mon, 19 Jul 2021 00:13:39 +0200 Subject: [PATCH] added account number field to user (#2671) --- src/Entity/User.php | 26 +++++++++++-- src/Form/UserEditType.php | 4 ++ src/Migrations/Version20210717211144.php | 38 +++++++++++++++++++ src/Repository/UserRepository.php | 1 + templates/user/index.html.twig | 2 + templates/user/profile.html.twig | 12 +++++- templates/user/stats.html.twig | 8 +++- tests/API/APIControllerBaseTest.php | 2 + tests/Entity/UserTest.php | 5 +++ tests/Export/Spreadsheet/UserExporterTest.php | 6 +++ translations/messages.de.xlf | 4 ++ translations/messages.en.xlf | 4 ++ 12 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 src/Migrations/Version20210717211144.php diff --git a/src/Entity/User.php b/src/Entity/User.php index 93b0ca8f..fb2d523e 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -56,7 +56,7 @@ use Symfony\Component\Validator\Constraints as Assert; * } * ) * - * @Exporter\Order({"id", "username", "alias", "title", "email", "last_login", "language", "timezone", "active", "registeredAt", "roles", "teams"}) + * @Exporter\Order({"id", "username", "alias", "title", "email", "last_login", "language", "timezone", "active", "registeredAt", "roles", "teams", "color", "accountNumber"}) * @Exporter\Expose("email", label="label.email", exp="object.getEmail()") * @Exporter\Expose("username", label="label.username", exp="object.getUsername()") * @Exporter\Expose("timezone", label="label.timezone", exp="object.getTimezone()") @@ -85,7 +85,6 @@ class User implements UserInterface, EquatableInterface, \Serializable * Internal ID * * @var int - * @internal must be protected because of parent class * * @Serializer\Expose() * @Serializer\Groups({"Default"}) @@ -96,7 +95,7 @@ class User implements UserInterface, EquatableInterface, \Serializable * @ORM\GeneratedValue * @ORM\Column(name="id", type="integer") */ - protected $id; + private $id; /** * The user alias will be displayed in the frontend instead of the username * @@ -227,6 +226,17 @@ class User implements UserInterface, EquatableInterface, \Serializable * @Assert\Email(groups={"Registration", "UserCreate", "Profile"}) */ private $email; + /** + * @Serializer\Expose() + * @Serializer\Groups({"Default"}) + * + * @Exporter\Expose(label="label.account_number") + * + * @var string|null + * @ORM\Column(name="account", type="string", length=30, nullable=true) + * @Assert\Length(allowEmptyString=true, max="30", groups={"Registration", "UserCreate", "Profile"}) + */ + private $accountNumber; /** * @Serializer\Expose() * @Serializer\Groups({"Default"}) @@ -934,4 +944,14 @@ class User implements UserInterface, EquatableInterface, \Serializable return $initial; } + + public function getAccountNumber(): ?string + { + return $this->accountNumber; + } + + public function setAccountNumber(?string $accountNumber): void + { + $this->accountNumber = $accountNumber; + } } diff --git a/src/Form/UserEditType.php b/src/Form/UserEditType.php index 5f38a3ac..80b1f289 100644 --- a/src/Form/UserEditType.php +++ b/src/Form/UserEditType.php @@ -49,6 +49,10 @@ class UserEditType extends AbstractType 'label' => 'label.title', 'required' => false, ]) + ->add('accountNumber', TextType::class, [ + 'label' => 'label.account_number', + 'required' => false, + ]) ; if ($this->configuration->isThemeAllowAvatarUrls()) { diff --git a/src/Migrations/Version20210717211144.php b/src/Migrations/Version20210717211144.php new file mode 100644 index 00000000..515bd1f2 --- /dev/null +++ b/src/Migrations/Version20210717211144.php @@ -0,0 +1,38 @@ +getTable('kimai2_users'); + $users->addColumn('account', 'string', ['length' => 30, 'notnull' => false, 'default' => null]); + } + + public function down(Schema $schema): void + { + $users = $schema->getTable('kimai2_users'); + $users->dropColumn('account'); + } +} diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 7b1ab448..92914c95 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -291,6 +291,7 @@ class UserRepository extends EntityRepository implements UserLoaderInterface $qb->expr()->orX( $qb->expr()->like('u.alias', ':searchTerm'), $qb->expr()->like('u.title', ':searchTerm'), + $qb->expr()->like('u.accountNumber', ':searchTerm'), $qb->expr()->like('u.email', ':searchTerm'), $qb->expr()->like('u.username', ':searchTerm') ) diff --git a/templates/user/index.html.twig b/templates/user/index.html.twig index 0a182eb1..195bd052 100644 --- a/templates/user/index.html.twig +++ b/templates/user/index.html.twig @@ -7,6 +7,7 @@ {% set columns = { 'avatar': {'class': 'alwaysVisible w-min', 'title': null, 'orderBy': false}, 'alias': {'class': 'alwaysVisible'}, + 'account_number': {'class': 'hidden-xs hidden-sm hidden'}, 'title': {'class': 'hidden-xs hidden-sm hidden'}, 'email': {'class': 'hidden-xs hidden-sm hidden', 'orderBy': false}, 'lastLogin': {'class': 'hidden-xs hidden-sm hidden', 'orderBy': false}, @@ -44,6 +45,7 @@ {{ widgets.user_avatar(entry) }} {{ widgets.username(entry) }} + {{ entry.accountNumber }} {{ entry.title }} {{ entry.email }} {% if entry.lastLogin is not null %}{{ entry.lastLogin|date_full }}{% endif %} diff --git a/templates/user/profile.html.twig b/templates/user/profile.html.twig index 0dfd0dff..b97fc596 100644 --- a/templates/user/profile.html.twig +++ b/templates/user/profile.html.twig @@ -8,13 +8,21 @@ {% block box_body %} {{ form_start(form) }}
-
+
{{ form_row(form.alias) }}
-
+
{{ form_row(form.color) }}
+
+
+ {{ form_row(form.title) }} +
+
+ {{ form_row(form.accountNumber) }} +
+
{{ form_widget(form) }} {{ form_end(form) }} diff --git a/templates/user/stats.html.twig b/templates/user/stats.html.twig index 0a35c1dc..b28a8d43 100644 --- a/templates/user/stats.html.twig +++ b/templates/user/stats.html.twig @@ -81,9 +81,12 @@ {{ 'label.username'|trans }}
{{ user.username }}

+

+ {{ 'label.account_number'|trans }}
+ {{ user.accountNumber }} +

{{ 'profile.first_entry'|trans }}
- {# FIXME use a configuration for it #} {{ stats.firstEntry|date_short }}

@@ -152,6 +155,9 @@

{{ widgets.username(user) }} + {% if user.displayName != user.username %} + ({{ user.username }}) + {% endif %}

{{ user.title }}
diff --git a/tests/API/APIControllerBaseTest.php b/tests/API/APIControllerBaseTest.php index a64cb99c..5fc3741b 100644 --- a/tests/API/APIControllerBaseTest.php +++ b/tests/API/APIControllerBaseTest.php @@ -292,6 +292,7 @@ abstract class APIControllerBaseTest extends ControllerBaseTest 'enabled' => 'bool', 'color' => '@string', 'alias' => '@string', + 'accountNumber' => '@string', ]; // if a user is loaded explicitly @@ -308,6 +309,7 @@ abstract class APIControllerBaseTest extends ControllerBaseTest 'roles' => ['result' => 'array', 'type' => 'string'], 'language' => 'string', 'timezone' => 'string', + 'accountNumber' => '@string', ]; // if a team is embedded diff --git a/tests/Entity/UserTest.php b/tests/Entity/UserTest.php index 022bf3f7..8639e2d8 100644 --- a/tests/Entity/UserTest.php +++ b/tests/Entity/UserTest.php @@ -39,6 +39,7 @@ class UserTest extends TestCase self::assertNull($user->getAvatar()); self::assertNull($user->getAlias()); self::assertNull($user->getId()); + self::assertNull($user->getAccountNumber()); self::assertNull($user->getApiToken()); self::assertNull($user->getPlainApiToken()); self::assertNull($user->getPasswordRequestedAt()); @@ -59,6 +60,9 @@ class UserTest extends TestCase $user->setTitle('Mr. Code Blaster'); self::assertEquals('Mr. Code Blaster', $user->getTitle()); + + $user->setAccountNumber('A-058375'); + self::assertEquals('A-058375', $user->getAccountNumber()); } public function testColor() @@ -334,6 +338,7 @@ class UserTest extends TestCase ['profile.registration_date', 'datetime'], ['label.roles', 'array'], ['label.color', 'string'], + ['label.account_number', 'string'], ]; self::assertCount(\count($expected), $columns); diff --git a/tests/Export/Spreadsheet/UserExporterTest.php b/tests/Export/Spreadsheet/UserExporterTest.php index f3df3a97..afc4fdb5 100644 --- a/tests/Export/Spreadsheet/UserExporterTest.php +++ b/tests/Export/Spreadsheet/UserExporterTest.php @@ -32,15 +32,18 @@ class UserExporterTest extends TestCase $userPreferenceExtractor = new UserPreferenceExtractor($this->createMock(EventDispatcherInterface::class)); $user = new User(); + $user->setAccountNumber('F-747864'); $user->setUsername('test user'); $user->setAvatar('Lorem Ipsum'); $user->setTimezone('Europe/Berlin'); + $user->setColor('#ececec'); $user->setAlias('Another name'); $user->setTitle('Mr. Title'); $user->setLanguage('de'); $user->setEmail('test@example.com'); $user->setEnabled(false); $user->addRole(User::ROLE_TEAMLEAD); + $date = $user->getRegisteredAt(); $sut = new UserExporter($spreadsheetExporter, $annotationExtractor, $userPreferenceExtractor); $spreadsheet = $sut->export([$user], new UserPreferenceDisplayEvent(UserPreferenceDisplayEvent::EXPORT)); @@ -55,6 +58,9 @@ class UserExporterTest extends TestCase self::assertEquals('de', $worksheet->getCellByColumnAndRow(7, 2)->getValue()); self::assertEquals('Europe/Berlin', $worksheet->getCellByColumnAndRow(8, 2)->getValue()); self::assertFalse($worksheet->getCellByColumnAndRow(9, 2)->getValue()); + self::assertEquals($date->format('Y-m-d H:i'), $worksheet->getCellByColumnAndRow(10, 2)->getFormattedValue()); self::assertEquals('ROLE_TEAMLEAD;ROLE_USER', $worksheet->getCellByColumnAndRow(11, 2)->getValue()); + self::assertEquals('#ececec', $worksheet->getCellByColumnAndRow(12, 2)->getValue()); + self::assertEquals('F-747864', $worksheet->getCellByColumnAndRow(13, 2)->getValue()); } } diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index 86810cc6..f2915479 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -1243,6 +1243,10 @@ label.last_record Letzter Eintrag + + label.account_number + Personalnummer + diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 94857130..0544947e 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -1243,6 +1243,10 @@ label.last_record Last entry + + label.account_number + Staff number +