added account number field to user (#2671)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
38
src/Migrations/Version20210717211144.php
Normal file
38
src/Migrations/Version20210717211144.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* @version 1.15
|
||||
*/
|
||||
final class Version20210717211144 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$users = $schema->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');
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
)
|
||||
|
||||
@@ -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 @@
|
||||
<tr {{ widgets.user_row_attr(entry) }}>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'avatar') }}">{{ widgets.user_avatar(entry) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'alias') }}">{{ widgets.username(entry) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'account_number') }}">{{ entry.accountNumber }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'title') }}">{{ entry.title }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'email') }}">{{ entry.email }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'lastLogin') }}">{% if entry.lastLogin is not null %}{{ entry.lastLogin|date_full }}{% endif %}</td>
|
||||
|
||||
@@ -8,13 +8,21 @@
|
||||
{% block box_body %}
|
||||
{{ form_start(form) }}
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
<div class="col-md-9">
|
||||
{{ form_row(form.alias) }}
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
{{ form_row(form.color) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
{{ form_row(form.title) }}
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
{{ form_row(form.accountNumber) }}
|
||||
</div>
|
||||
</div>
|
||||
{{ form_widget(form) }}
|
||||
<input type="submit" value="{{ 'action.save'|trans }}" class="btn btn-primary" />
|
||||
{{ form_end(form) }}
|
||||
|
||||
@@ -81,9 +81,12 @@
|
||||
<strong>{{ 'label.username'|trans }}</strong><br>
|
||||
{{ user.username }}
|
||||
</p>
|
||||
<p>
|
||||
<strong>{{ 'label.account_number'|trans }}</strong><br>
|
||||
{{ user.accountNumber }}
|
||||
</p>
|
||||
<p>
|
||||
<strong>{{ 'profile.first_entry'|trans }}</strong><br>
|
||||
{# FIXME use a configuration for it #}
|
||||
{{ stats.firstEntry|date_short }}
|
||||
</p>
|
||||
<p>
|
||||
@@ -152,6 +155,9 @@
|
||||
<div class="widget-user-header" style="{% if config.image is not null %}background: url('{{ config.image }}') center center;{% else %}background-color: {{ config.color }}{% endif %}">
|
||||
<h3 class="widget-user-username" style="color: {{ config.font }}">
|
||||
{{ widgets.username(user) }}
|
||||
{% if user.displayName != user.username %}
|
||||
({{ user.username }})
|
||||
{% endif %}
|
||||
</h3>
|
||||
<h5 class="widget-user-desc" style="color: {{ config.font }}">{{ user.title }}</h5>
|
||||
</div>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1243,6 +1243,10 @@
|
||||
<source>label.last_record</source>
|
||||
<target>Letzter Eintrag</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="label.account_number">
|
||||
<source>label.account_number</source>
|
||||
<target>Personalnummer</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
||||
@@ -1243,6 +1243,10 @@
|
||||
<source>label.last_record</source>
|
||||
<target>Last entry</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="label.account_number">
|
||||
<source>label.account_number</source>
|
||||
<target>Staff number</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
||||
Reference in New Issue
Block a user