mirror of
https://github.com/Karaka-Management/oms-HumanResourceTimeRecording.git
synced 2026-02-12 18:58:41 +00:00
ui fixes
This commit is contained in:
parent
4e81fb41cf
commit
a8d5939460
|
|
@ -5,6 +5,7 @@ return [
|
||||||
0 => [
|
0 => [
|
||||||
'dest' => '\Modules\HumanResourceTimeRecording\Controller\TimerecordingController:viewDashboard',
|
'dest' => '\Modules\HumanResourceTimeRecording\Controller\TimerecordingController:viewDashboard',
|
||||||
'verb' => 1,
|
'verb' => 1,
|
||||||
|
'active' => true,
|
||||||
'permission' => [
|
'permission' => [
|
||||||
'module' => 'HumanResourceTimeRecording',
|
'module' => 'HumanResourceTimeRecording',
|
||||||
'type' => 2,
|
'type' => 2,
|
||||||
|
|
@ -16,6 +17,7 @@ return [
|
||||||
0 => [
|
0 => [
|
||||||
'dest' => '\Modules\HumanResourceTimeRecording\Controller\TimerecordingController:viewDashboard',
|
'dest' => '\Modules\HumanResourceTimeRecording\Controller\TimerecordingController:viewDashboard',
|
||||||
'verb' => 1,
|
'verb' => 1,
|
||||||
|
'active' => true,
|
||||||
'permission' => [
|
'permission' => [
|
||||||
'module' => 'HumanResourceTimeRecording',
|
'module' => 'HumanResourceTimeRecording',
|
||||||
'type' => 2,
|
'type' => 2,
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"pid": "/humanresource/timerecording",
|
"pid": "/humanresource/timerecording",
|
||||||
"type": 3,
|
"type": 3,
|
||||||
"subtype": 1,
|
"subtype": 1,
|
||||||
"name": "Today",
|
"name": "Dashboard",
|
||||||
"uri": "{/base}/humanresource/timerecording/dashboard?{?}",
|
"uri": "{/base}/humanresource/timerecording/dashboard?{?}",
|
||||||
"target": "self",
|
"target": "self",
|
||||||
"icon": null,
|
"icon": null,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ return [
|
||||||
'dest' => '\Modules\HumanResourceTimeRecording\Controller\ApiController:apiSessionCreate',
|
'dest' => '\Modules\HumanResourceTimeRecording\Controller\ApiController:apiSessionCreate',
|
||||||
'verb' => RouteVerb::PUT,
|
'verb' => RouteVerb::PUT,
|
||||||
'csrf' => true,
|
'csrf' => true,
|
||||||
|
'active' => true,
|
||||||
'permission' => [
|
'permission' => [
|
||||||
'module' => ApiController::NAME,
|
'module' => ApiController::NAME,
|
||||||
'type' => PermissionType::CREATE,
|
'type' => PermissionType::CREATE,
|
||||||
|
|
@ -35,6 +36,7 @@ return [
|
||||||
'dest' => '\Modules\HumanResourceTimeRecording\Controller\ApiController:apiSessionElementCreate',
|
'dest' => '\Modules\HumanResourceTimeRecording\Controller\ApiController:apiSessionElementCreate',
|
||||||
'verb' => RouteVerb::PUT,
|
'verb' => RouteVerb::PUT,
|
||||||
'csrf' => true,
|
'csrf' => true,
|
||||||
|
'active' => true,
|
||||||
'permission' => [
|
'permission' => [
|
||||||
'module' => ApiController::NAME,
|
'module' => ApiController::NAME,
|
||||||
'type' => PermissionType::CREATE,
|
'type' => PermissionType::CREATE,
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ return [
|
||||||
[
|
[
|
||||||
'dest' => '\Modules\HumanResourceTimeRecording\Controller\BackendController:viewDashboard',
|
'dest' => '\Modules\HumanResourceTimeRecording\Controller\BackendController:viewDashboard',
|
||||||
'verb' => RouteVerb::GET,
|
'verb' => RouteVerb::GET,
|
||||||
|
'active' => true,
|
||||||
'permission' => [
|
'permission' => [
|
||||||
'module' => BackendController::NAME,
|
'module' => BackendController::NAME,
|
||||||
'type' => PermissionType::READ,
|
'type' => PermissionType::READ,
|
||||||
|
|
@ -33,6 +34,7 @@ return [
|
||||||
[
|
[
|
||||||
'dest' => '\Modules\HumanResourceTimeRecording\Controller\BackendController:viewPrivateDashboard',
|
'dest' => '\Modules\HumanResourceTimeRecording\Controller\BackendController:viewPrivateDashboard',
|
||||||
'verb' => RouteVerb::GET,
|
'verb' => RouteVerb::GET,
|
||||||
|
'active' => true,
|
||||||
'permission' => [
|
'permission' => [
|
||||||
'module' => BackendController::NAME,
|
'module' => BackendController::NAME,
|
||||||
'type' => PermissionType::READ,
|
'type' => PermissionType::READ,
|
||||||
|
|
@ -44,6 +46,7 @@ return [
|
||||||
[
|
[
|
||||||
'dest' => '\Modules\HumanResourceTimeRecording\Controller\BackendController:viewPrivateSession',
|
'dest' => '\Modules\HumanResourceTimeRecording\Controller\BackendController:viewPrivateSession',
|
||||||
'verb' => RouteVerb::GET,
|
'verb' => RouteVerb::GET,
|
||||||
|
'active' => true,
|
||||||
'permission' => [
|
'permission' => [
|
||||||
'module' => BackendController::NAME,
|
'module' => BackendController::NAME,
|
||||||
'type' => PermissionType::READ,
|
'type' => PermissionType::READ,
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,8 @@ final class ApiController extends Controller
|
||||||
$element = new SessionElement($session, $dt);
|
$element = new SessionElement($session, $dt);
|
||||||
$element->status = ClockingStatus::tryFromValue($request->getDataInt('status')) ?? ClockingStatus::START;
|
$element->status = ClockingStatus::tryFromValue($request->getDataInt('status')) ?? ClockingStatus::START;
|
||||||
|
|
||||||
$session->addSessionElement($element);
|
$session->sessionElements[] = $element;
|
||||||
|
$session->recalculate();
|
||||||
|
|
||||||
return $session;
|
return $session;
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +112,9 @@ final class ApiController extends Controller
|
||||||
*/
|
*/
|
||||||
public function apiSessionElementCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
|
public function apiSessionElementCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
|
||||||
{
|
{
|
||||||
if (($request->getDataInt('status') ?? -1) === ClockingStatus::START) {
|
if (!$request->hasData('session') &&
|
||||||
|
($request->getDataInt('status') ?? -1) === ClockingStatus::START
|
||||||
|
) {
|
||||||
$this->apiSessionCreate($request, $response);
|
$this->apiSessionCreate($request, $response);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -146,9 +149,12 @@ final class ApiController extends Controller
|
||||||
|
|
||||||
if ($element->status === ClockingStatus::END) {
|
if ($element->status === ClockingStatus::END) {
|
||||||
/** @var \Modules\HumanResourceTimeRecording\Models\Session $session */
|
/** @var \Modules\HumanResourceTimeRecording\Models\Session $session */
|
||||||
$session = SessionMapper::get()->where('id', (int) $request->getData('session'))->execute();
|
$session = SessionMapper::get()
|
||||||
|
->with('sessionElements')
|
||||||
|
->where('id', (int) $request->getData('session'))
|
||||||
|
->execute();
|
||||||
|
|
||||||
$session->addSessionElement($element);
|
$session->recalculate();
|
||||||
SessionMapper::update()->execute($session);
|
SessionMapper::update()->execute($session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,56 +105,35 @@ class Session implements \JsonSerializable
|
||||||
$this->createdAt = new \DateTimeImmutable('now');
|
$this->createdAt = new \DateTimeImmutable('now');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function recalculate() : void
|
||||||
* Get busy time.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public function getBusy() : int
|
|
||||||
{
|
{
|
||||||
return $this->busy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a session element to the session
|
|
||||||
*
|
|
||||||
* @param SessionElement $element Session element
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public function addSessionElement(SessionElement $element) : void
|
|
||||||
{
|
|
||||||
if ($element->status === ClockingStatus::START) {
|
|
||||||
foreach ($this->sessionElements as $e) {
|
|
||||||
if ($e->status === ClockingStatus::START) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->start = $element->datetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($element->status === ClockingStatus::END) {
|
|
||||||
if ($this->end !== null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->end = $element->datetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->sessionElements[] = $element;
|
|
||||||
|
|
||||||
\usort($this->sessionElements, [$this, 'compareSessionElementTimestamps']);
|
\usort($this->sessionElements, [$this, 'compareSessionElementTimestamps']);
|
||||||
|
|
||||||
|
$start = null;
|
||||||
|
$end = null;
|
||||||
|
|
||||||
|
foreach ($this->sessionElements as $e) {
|
||||||
|
if ($e->status === ClockingStatus::START
|
||||||
|
&& ($start === null || $start->getTimestamp() > $e->datetime->getTimestamp())
|
||||||
|
) {
|
||||||
|
$start = $e->datetime;
|
||||||
|
} elseif ($e->status === ClockingStatus::END
|
||||||
|
&& ($end === null || $end->getTimestamp() < $e->datetime->getTimestamp())
|
||||||
|
) {
|
||||||
|
$end = $e->datetime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->start = $start;
|
||||||
|
$this->end = $end;
|
||||||
|
|
||||||
$busyTime = 0;
|
$busyTime = 0;
|
||||||
$lastStart = $this->start;
|
$lastStart = $this->start;
|
||||||
|
|
||||||
foreach ($this->sessionElements as $e) {
|
foreach ($this->sessionElements as $e) {
|
||||||
if ($e->status === ClockingStatus::START) {
|
if ($e->status === ClockingStatus::START) {
|
||||||
|
$lastStart = $e->datetime;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Modules\HumanResourceTimeRecording\Models;
|
||||||
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper class.
|
* SessionElement mapper class.
|
||||||
*
|
*
|
||||||
* @package Modules\HumanResourceTimeRecording\Models
|
* @package Modules\HumanResourceTimeRecording\Models
|
||||||
* @license OMS License 2.0
|
* @license OMS License 2.0
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ use phpOMS\DataStorage\Database\Query\Builder;
|
||||||
use phpOMS\Stdlib\Base\SmartDateTime;
|
use phpOMS\Stdlib\Base\SmartDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper class.
|
* Session mapper class.
|
||||||
*
|
*
|
||||||
* @package Modules\HumanResourceTimeRecording\Models
|
* @package Modules\HumanResourceTimeRecording\Models
|
||||||
* @license OMS License 2.0
|
* @license OMS License 2.0
|
||||||
|
|
@ -105,6 +105,8 @@ final class SessionMapper extends DataMapperFactory
|
||||||
*
|
*
|
||||||
* @return Session[]
|
* @return Session[]
|
||||||
*
|
*
|
||||||
|
* @performance This is way too slow
|
||||||
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function getLastSessionsFromAllEmployees() : array
|
public static function getLastSessionsFromAllEmployees() : array
|
||||||
|
|
@ -121,7 +123,7 @@ final class SessionMapper extends DataMapperFactory
|
||||||
->andOn(self::TABLE . '_d1.hr_timerecording_session_start', '=', 'tm.maxDate');
|
->andOn(self::TABLE . '_d1.hr_timerecording_session_start', '=', 'tm.maxDate');
|
||||||
|
|
||||||
return self::getAll()
|
return self::getAll()
|
||||||
->execute($query);
|
->executeGetArray($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,5 @@ return ['Navigation' => [
|
||||||
'List' => 'Liste',
|
'List' => 'Liste',
|
||||||
'Stats' => 'Statistiken',
|
'Stats' => 'Statistiken',
|
||||||
'TimeRecording' => 'Zeitaufnahme',
|
'TimeRecording' => 'Zeitaufnahme',
|
||||||
'Today' => 'Heute',
|
'Dashboard' => 'Dashboard',
|
||||||
]];
|
]];
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,5 @@ return ['Navigation' => [
|
||||||
'List' => 'List',
|
'List' => 'List',
|
||||||
'Stats' => 'Stats',
|
'Stats' => 'Stats',
|
||||||
'TimeRecording' => 'Time Recording',
|
'TimeRecording' => 'Time Recording',
|
||||||
'Today' => 'Today',
|
'Dashboard' => 'Dashboard',
|
||||||
]];
|
]];
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Modules\HumanResourceTimeRecording\Models\ClockingType;
|
use Modules\HumanResourceTimeRecording\Models\ClockingType;
|
||||||
|
use phpOMS\Uri\UriFactory;
|
||||||
|
|
||||||
$date = new \DateTime('now');
|
$date = new \DateTime('now');
|
||||||
|
|
||||||
|
|
@ -36,17 +37,21 @@ echo $this->data['nav']->render(); ?>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($this->data['employees'] as $employee) :
|
<?php foreach ($this->data['employees'] as $employee) :
|
||||||
$session = $this->data['sessions'][$employee->id] ?? null;
|
$session = $this->data['sessions'][$employee->id] ?? null;
|
||||||
|
|
||||||
|
// @todo Implement clocking view per employee for HR (also to edit clocking)
|
||||||
|
$employeeUrl = UriFactory::build('{/base}/humanresource/staff/view?id=' . $employee->id);
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?= $session?->getStart()->format('Y-m-d') ?? $date->format('Y-m-d H:i:s'); ?>
|
<td><?= $session?->start->format('Y-m-d H:i:s') ?? $date->format('Y-m-d H:i:s'); ?>
|
||||||
<td><span class="tag"><?= $this->getHtml('CT' . ($session?->type ?? ClockingType::NO_DATA)); ?></span>
|
<td><span class="tag"><?= $this->getHtml('CT' . ($session?->type ?? ClockingType::NO_DATA)); ?></span>
|
||||||
<td>
|
<td><a class="content" href="<?= $employeeUrl; ?>">
|
||||||
<?= $this->printHtml($employee->profile->account->name1); ?>,
|
<?= $this->printHtml($employee->profile->account->name1); ?>,
|
||||||
<?= $this->printHtml($employee->profile->account->name2); ?>
|
<?= $this->printHtml($employee->profile->account->name2); ?>
|
||||||
<td><?= $session?->getStart()->format('H:i:s'); ?>
|
</a>
|
||||||
|
<td><?= $session?->start->format('H:i:s'); ?>
|
||||||
<td><?= $session !== null ? ((int) ($session->getBreak() / 3600)) . 'h' : ''; ?> <?= $session !== null ? ((int) ($session->getBreak() / 60) % 60) . 'm' : ''; ?>
|
<td><?= $session !== null ? ((int) ($session->getBreak() / 3600)) . 'h' : ''; ?> <?= $session !== null ? ((int) ($session->getBreak() / 60) % 60) . 'm' : ''; ?>
|
||||||
<td><?= $session?->getEnd() !== null ? $session->getEnd()->format('H:i') : ''; ?>
|
<td><?= $session?->end?->format('H:i') ?? ''; ?>
|
||||||
<td><?= $session !== null ? ((int) ($session->getBusy() / 3600)) . 'h' : ''; ?> <?= $session !== null ? ((int) ($session->getBusy() / 60) % 60) . 'm' : ''; ?>
|
<td><?= $session !== null ? ((int) ($session->busy / 3600)) . 'h' : ''; ?> <?= $session !== null ? ((int) ($session->busy / 60) % 60) . 'm' : ''; ?>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -222,9 +222,9 @@ echo $this->data['nav']->render(); ?>
|
||||||
<td><a href="<?= $url; ?>"><?= $session->start->format('H:i'); ?></a>
|
<td><a href="<?= $url; ?>"><?= $session->start->format('H:i'); ?></a>
|
||||||
<td><a href="<?= $url; ?>"><?= (int) ($session->getBreak() / 3600); ?>h <?= ((int) ($session->getBreak() / 60) % 60); ?>m</a>
|
<td><a href="<?= $url; ?>"><?= (int) ($session->getBreak() / 3600); ?>h <?= ((int) ($session->getBreak() / 60) % 60); ?>m</a>
|
||||||
<td><a href="<?= $url; ?>"><?= $session->end?->format('H:i'); ?></a>
|
<td><a href="<?= $url; ?>"><?= $session->end?->format('H:i'); ?></a>
|
||||||
<td><a href="<?= $url; ?>"><?= (int) ($session->getBusy() / 3600); ?>h <?= ((int) ($session->getBusy() / 60) % 60); ?>m</a>
|
<td><a href="<?= $url; ?>"><?= (int) ($session->busy / 3600); ?>h <?= ((int) ($session->busy / 60) % 60); ?>m</a>
|
||||||
<?php
|
<?php
|
||||||
$busy['week'] += $session->getBusy();
|
$busy['week'] += $session->busy;
|
||||||
if ($session->start->getTimestamp() < $startWeek->getTimestamp()
|
if ($session->start->getTimestamp() < $startWeek->getTimestamp()
|
||||||
|| $count === $sessionCount
|
|| $count === $sessionCount
|
||||||
) : ?>
|
) : ?>
|
||||||
|
|
@ -238,7 +238,7 @@ echo $this->data['nav']->render(); ?>
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<?php
|
<?php
|
||||||
$busy['month'] += $session->getBusy();
|
$busy['month'] += $session->busy;
|
||||||
if ($session->start->getTimestamp() < $startMonth->getTimestamp()
|
if ($session->start->getTimestamp() < $startMonth->getTimestamp()
|
||||||
|| $count === $sessionCount
|
|| $count === $sessionCount
|
||||||
) : ?>
|
) : ?>
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ echo $this->data['nav']->render(); ?>
|
||||||
<td><?= $session->getStart()->format('H:i'); ?>
|
<td><?= $session->getStart()->format('H:i'); ?>
|
||||||
<td><?= (int) ($session->getBreak() / 3600); ?>h <?= ((int) ($session->getBreak() / 60) % 60); ?>m
|
<td><?= (int) ($session->getBreak() / 3600); ?>h <?= ((int) ($session->getBreak() / 60) % 60); ?>m
|
||||||
<td><?= $session->getEnd() !== null ? $session->getEnd()->format('H:i') : ''; ?>
|
<td><?= $session->getEnd() !== null ? $session->getEnd()->format('H:i') : ''; ?>
|
||||||
<td><?= (int) ($session->getBusy() / 3600); ?>h <?= ((int) ($session->getBusy() / 60) % 60); ?>m
|
<td><?= (int) ($session->busy / 3600); ?>h <?= ((int) ($session->busy / 60) % 60); ?>m
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ final class SessionTest extends \PHPUnit\Framework\TestCase
|
||||||
public function testDefault() : void
|
public function testDefault() : void
|
||||||
{
|
{
|
||||||
self::assertEquals(0, $this->session->id);
|
self::assertEquals(0, $this->session->id);
|
||||||
self::assertEquals(0, $this->session->getBusy());
|
self::assertEquals(0, $this->session->busy);
|
||||||
self::assertEquals(0, $this->session->getBreak());
|
self::assertEquals(0, $this->session->getBreak());
|
||||||
self::assertEquals([], $this->session->getSessionElements());
|
self::assertEquals([], $this->session->getSessionElements());
|
||||||
self::assertEquals(ClockingType::OFFICE, $this->session->type);
|
self::assertEquals(ClockingType::OFFICE, $this->session->type);
|
||||||
|
|
@ -104,7 +104,7 @@ final class SessionTest extends \PHPUnit\Framework\TestCase
|
||||||
$this->session->addSessionElement($element);
|
$this->session->addSessionElement($element);
|
||||||
|
|
||||||
self::assertEquals(2 * 60 * 60, $this->session->getBreak());
|
self::assertEquals(2 * 60 * 60, $this->session->getBreak());
|
||||||
self::assertEquals(7 * 60 * 60, $this->session->getBusy());
|
self::assertEquals(7 * 60 * 60, $this->session->busy);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[\PHPUnit\Framework\Attributes\Group('module')]
|
#[\PHPUnit\Framework\Attributes\Group('module')]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user