mirror of
https://github.com/Karaka-Management/oms-HumanResourceTimeRecording.git
synced 2026-02-12 18:58:41 +00:00
Implemented basic time recording w/ frontend
This commit is contained in:
parent
5840080ee3
commit
4579fae4b2
|
|
@ -18,7 +18,22 @@
|
||||||
"pid": "/humanresource/timerecording",
|
"pid": "/humanresource/timerecording",
|
||||||
"type": 3,
|
"type": 3,
|
||||||
"subtype": 1,
|
"subtype": 1,
|
||||||
"name": "List",
|
"name": "Today",
|
||||||
|
"uri": "{/prefix}humanresource/timerecording/dashboard?{?}",
|
||||||
|
"target": "self",
|
||||||
|
"icon": null,
|
||||||
|
"order": 1,
|
||||||
|
"from": "HumanResourceTimeRecording",
|
||||||
|
"permission": { "permission": 2, "type": null, "element": null },
|
||||||
|
"parent": 1006301001,
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1006302002,
|
||||||
|
"pid": "/humanresource/timerecording",
|
||||||
|
"type": 3,
|
||||||
|
"subtype": 1,
|
||||||
|
"name": "Stats",
|
||||||
"uri": "{/prefix}humanresource/timerecording/dashboard?{?}",
|
"uri": "{/prefix}humanresource/timerecording/dashboard?{?}",
|
||||||
"target": "self",
|
"target": "self",
|
||||||
"icon": null,
|
"icon": null,
|
||||||
|
|
@ -36,7 +51,7 @@
|
||||||
"type": 2,
|
"type": 2,
|
||||||
"subtype": 1,
|
"subtype": 1,
|
||||||
"name": "TimeRecording",
|
"name": "TimeRecording",
|
||||||
"uri": "{/prefix}humanresource/timerecording/dashboard?{?}",
|
"uri": "{/prefix}private/timerecording/dashboard?{?}",
|
||||||
"target": "self",
|
"target": "self",
|
||||||
"icon": null,
|
"icon": null,
|
||||||
"order": 1,
|
"order": 1,
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@
|
||||||
"hr_timerecording_session_end": {
|
"hr_timerecording_session_end": {
|
||||||
"name": "hr_timerecording_session_end",
|
"name": "hr_timerecording_session_end",
|
||||||
"type": "DATETIME",
|
"type": "DATETIME",
|
||||||
"null": false
|
"null": true,
|
||||||
|
"default": null
|
||||||
},
|
},
|
||||||
"hr_timerecording_session_busy": {
|
"hr_timerecording_session_busy": {
|
||||||
"name": "hr_timerecording_session_busy",
|
"name": "hr_timerecording_session_busy",
|
||||||
|
|
@ -48,8 +49,8 @@
|
||||||
"primary": true,
|
"primary": true,
|
||||||
"autoincrement": true
|
"autoincrement": true
|
||||||
},
|
},
|
||||||
"hr_timerecording_session_element_type": {
|
"hr_timerecording_session_element_status": {
|
||||||
"name": "hr_timerecording_session_element_type",
|
"name": "hr_timerecording_session_element_status",
|
||||||
"type": "TINYINT",
|
"type": "TINYINT",
|
||||||
"null": false
|
"null": false
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,15 @@ return [
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'^.*/private/timerecording/dashboard.*$' => [
|
||||||
|
[
|
||||||
|
'dest' => '\Modules\HumanResourceTimeRecording\Controller\BackendController:viewPrivateDashboard',
|
||||||
|
'verb' => RouteVerb::GET,
|
||||||
|
'permission' => [
|
||||||
|
'module' => BackendController::MODULE_NAME,
|
||||||
|
'type' => PermissionType::READ,
|
||||||
|
'state' => PermissionState::PRIVATE_DASHBOARD,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ use phpOMS\Contract\RenderableInterface;
|
||||||
use phpOMS\Message\RequestAbstract;
|
use phpOMS\Message\RequestAbstract;
|
||||||
use phpOMS\Message\ResponseAbstract;
|
use phpOMS\Message\ResponseAbstract;
|
||||||
use phpOMS\Views\View;
|
use phpOMS\Views\View;
|
||||||
|
use Modules\HumanResourceTimeRecording\Models\SessionMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TimeRecording controller class.
|
* TimeRecording controller class.
|
||||||
|
|
@ -48,6 +49,33 @@ final class BackendController extends Controller
|
||||||
$view->setTemplate('/Modules/HumanResourceTimeRecording/Theme/Backend/dashboard');
|
$view->setTemplate('/Modules/HumanResourceTimeRecording/Theme/Backend/dashboard');
|
||||||
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1006301001, $request, $response));
|
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1006301001, $request, $response));
|
||||||
|
|
||||||
|
$list = SessionMapper::getLastSessionsForDate(new \DateTime('now'));
|
||||||
|
$view->addData('sessions', $list);
|
||||||
|
|
||||||
|
return $view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Routing end-point for application behaviour.
|
||||||
|
*
|
||||||
|
* @param RequestAbstract $request Request
|
||||||
|
* @param ResponseAbstract $response Response
|
||||||
|
* @param mixed $data Generic data
|
||||||
|
*
|
||||||
|
* @return RenderableInterface
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function viewPrivateDashboard(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
|
||||||
|
{
|
||||||
|
$view = new View($this->app, $request, $response);
|
||||||
|
$view->setTemplate('/Modules/HumanResourceTimeRecording/Theme/Backend/private-dashboard');
|
||||||
|
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1006303001, $request, $response));
|
||||||
|
|
||||||
|
$list = SessionMapper::getNewest(50);
|
||||||
|
$view->addData('sessions', $list);
|
||||||
|
|
||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,5 +26,6 @@ use phpOMS\Stdlib\Base\Enum;
|
||||||
*/
|
*/
|
||||||
abstract class PermissionState extends Enum
|
abstract class PermissionState extends Enum
|
||||||
{
|
{
|
||||||
public const DASHBOARD = 1;
|
public const DASHBOARD = 1;
|
||||||
|
public const PRIVATE_DASHBOARD = 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,14 @@ class Session implements ArrayableInterface, \JsonSerializable
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
|
* @param int|Employee $employee Employee
|
||||||
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct($employee = 0)
|
||||||
{
|
{
|
||||||
$this->start = new \DateTime('now');
|
$this->start = new \DateTime('now');
|
||||||
|
$this->employee = $employee;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -104,6 +107,18 @@ class Session implements ArrayableInterface, \JsonSerializable
|
||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get employee.
|
||||||
|
*
|
||||||
|
* @return int|Employee
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getEmployee()
|
||||||
|
{
|
||||||
|
return $this->employee;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a session element to the session
|
* Add a session element to the session
|
||||||
*
|
*
|
||||||
|
|
@ -115,9 +130,75 @@ class Session implements ArrayableInterface, \JsonSerializable
|
||||||
*/
|
*/
|
||||||
public function addSessionElement($element) : void
|
public function addSessionElement($element) : void
|
||||||
{
|
{
|
||||||
$this->sessionElement[] = $element;
|
if ($element->getStatus() === ClockingStatus::START) {
|
||||||
|
// todo: prevent multiple starts and ends per session?
|
||||||
|
|
||||||
// todo: if quit element or pause element re-calculate busy time!
|
$this->start = $element->getDatetime();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($element->getStatus() === ClockingStatus::END) {
|
||||||
|
// todo: prevent multiple starts and ends per session?
|
||||||
|
|
||||||
|
$this->end = $element->getDatetime();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sessionElements[] = $element;
|
||||||
|
|
||||||
|
\usort($this->sessionElements, function($a, $b) {
|
||||||
|
return $a->getDatetime()->getTimestamp() <=> $b->getDatetime()->getTimestamp();
|
||||||
|
});
|
||||||
|
|
||||||
|
$busyTime = 0;
|
||||||
|
$lastStart = $this->start;
|
||||||
|
|
||||||
|
foreach ($this->sessionElements as $e) {
|
||||||
|
if ($e->getStatus() === ClockingStatus::START) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($e->getStatus() === ClockingStatus::PAUSE || $e->getStatus() === ClockingStatus::END) {
|
||||||
|
$busyTime += $e->getDatetime()->getTimestamp() - $lastStart->getTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($e->getStatus() === ClockingStatus::CONTINUE) {
|
||||||
|
$lastStart = $e->getDatetime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->busy = $busyTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total break time of a session
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getBreak() : int
|
||||||
|
{
|
||||||
|
\usort($this->sessionElements, function($a, $b) {
|
||||||
|
return $a->getDatetime()->getTimestamp() <=> $b->getDatetime()->getTimestamp();
|
||||||
|
});
|
||||||
|
|
||||||
|
$breakTime = 0;
|
||||||
|
$lastBreak = $this->start;
|
||||||
|
|
||||||
|
foreach ($this->sessionElements as $element) {
|
||||||
|
if ($element->getStatus() === ClockingStatus::START) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($element->getStatus() === ClockingStatus::PAUSE || $element->getStatus() === ClockingStatus::END) {
|
||||||
|
$lastBreak = $element->getDatetime();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($element->getStatus() === ClockingStatus::CONTINUE) {
|
||||||
|
$breakTime += $element->getDatetime()->getTimestamp() - ($lastBreak->getTimestamp() ?? 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $breakTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,12 @@ class SessionElement implements ArrayableInterface, \JsonSerializable
|
||||||
private int $id = 0;
|
private int $id = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Session element type.
|
* Session element status.
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private int $type = ClockingStatus::START;
|
private int $status = ClockingStatus::START;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DateTime
|
* DateTime
|
||||||
|
|
@ -53,10 +53,10 @@ class SessionElement implements ArrayableInterface, \JsonSerializable
|
||||||
/**
|
/**
|
||||||
* Session id this element belongs to
|
* Session id this element belongs to
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int|Session
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private int $session = 0;
|
private $session = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
|
|
@ -66,7 +66,7 @@ class SessionElement implements ArrayableInterface, \JsonSerializable
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function __construct(int $session = 0, \DateTime $dt = null)
|
public function __construct($session = 0, \DateTime $dt = null)
|
||||||
{
|
{
|
||||||
$this->session = $session;
|
$this->session = $session;
|
||||||
$this->dt = $dt ?? new \DateTime('now');
|
$this->dt = $dt ?? new \DateTime('now');
|
||||||
|
|
@ -97,29 +97,41 @@ class SessionElement implements ArrayableInterface, \JsonSerializable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the session element type
|
* Get the session element status
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function getType() : int
|
public function getStatus() : int
|
||||||
{
|
{
|
||||||
return $this->type;
|
return $this->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the session element type
|
* Set the session element status
|
||||||
*
|
*
|
||||||
* @param int $type Session element type
|
* @param int $status Session element status
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function setType(int $type) : void
|
public function setStatus(int $status) : void
|
||||||
{
|
{
|
||||||
$this->type = $type;
|
$this->status = $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get session this element is for
|
||||||
|
*
|
||||||
|
* @return int|Session
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getSession()
|
||||||
|
{
|
||||||
|
return $this->session;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -129,7 +141,7 @@ class SessionElement implements ArrayableInterface, \JsonSerializable
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'type' => $this->type,
|
'status' => $this->status,
|
||||||
'dt' => $this->dt->format('Y-m-d H:i:s'),
|
'dt' => $this->dt->format('Y-m-d H:i:s'),
|
||||||
'sesseion' => $this->session,
|
'sesseion' => $this->session,
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,24 @@ final class SessionElementMapper extends DataMapperAbstract
|
||||||
*/
|
*/
|
||||||
protected static array $columns = [
|
protected static array $columns = [
|
||||||
'hr_timerecording_session_element_id' => ['name' => 'hr_timerecording_session_element_id', 'type' => 'int', 'internal' => 'id'],
|
'hr_timerecording_session_element_id' => ['name' => 'hr_timerecording_session_element_id', 'type' => 'int', 'internal' => 'id'],
|
||||||
'hr_timerecording_session_element_type' => ['name' => 'hr_timerecording_session_element_type', 'type' => 'int', 'internal' => 'type'],
|
'hr_timerecording_session_element_status' => ['name' => 'hr_timerecording_session_element_status', 'type' => 'int', 'internal' => 'status'],
|
||||||
'hr_timerecording_session_element_dt' => ['name' => 'hr_timerecording_session_element_dt', 'type' => 'DateTime', 'internal' => 'dt'],
|
'hr_timerecording_session_element_dt' => ['name' => 'hr_timerecording_session_element_dt', 'type' => 'DateTime', 'internal' => 'dt'],
|
||||||
'hr_timerecording_session_element_session' => ['name' => 'hr_timerecording_session_element_session', 'type' => 'int', 'internal' => 'session'],
|
'hr_timerecording_session_element_session' => ['name' => 'hr_timerecording_session_element_session', 'type' => 'int', 'internal' => 'session'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Belongs to.
|
||||||
|
*
|
||||||
|
* @var array<string, array<string, string>>
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
protected static array $belongsTo = [
|
||||||
|
'session' => [
|
||||||
|
'mapper' => SessionMapper::class,
|
||||||
|
'src' => 'hr_timerecording_session_element_session',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Primary table.
|
* Primary table.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ namespace Modules\HumanResourceTimeRecording\Models;
|
||||||
|
|
||||||
use Modules\HumanResourceManagement\Models\EmployeeMapper;
|
use Modules\HumanResourceManagement\Models\EmployeeMapper;
|
||||||
use phpOMS\DataStorage\Database\DataMapperAbstract;
|
use phpOMS\DataStorage\Database\DataMapperAbstract;
|
||||||
|
use phpOMS\DataStorage\Database\Query\Builder;
|
||||||
|
use phpOMS\DataStorage\Database\RelationType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper class.
|
* Mapper class.
|
||||||
|
|
@ -86,4 +88,41 @@ final class SessionMapper extends DataMapperAbstract
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
protected static string $primaryField = 'hr_timerecording_session_id';
|
protected static string $primaryField = 'hr_timerecording_session_id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created at column
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
protected static string $createdAt = 'hr_timerecording_session_start';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get last sessions from all employees
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @todo: consider selecting only active employees
|
||||||
|
* @todo: consider using a datetime to limit the results to look for
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public static function getLastSessionsForDate(\DateTime $dt = null) : array
|
||||||
|
{
|
||||||
|
$join = new Builder(self::$db);
|
||||||
|
$join->prefix(self::$db->getPrefix())
|
||||||
|
->select(self::$table . '.hr_timerecording_session_employee')
|
||||||
|
->selectAs('MAX(hr_timerecording_session_start)', 'maxDate')
|
||||||
|
->from(self::$table)
|
||||||
|
->groupBy(self::$table . '.hr_timerecording_session_employee');
|
||||||
|
|
||||||
|
$query = new Builder(self::$db);
|
||||||
|
$query->prefix(self::$db->getPrefix())
|
||||||
|
->select('*')->fromAs(self::$table, 't')
|
||||||
|
->innerJoin($join, 'tm')
|
||||||
|
->on('t.hr_timerecording_session_employee', '=', 'tm.hr_timerecording_session_employee')
|
||||||
|
->andOn('t.hr_timerecording_session_start', '=', 'tm.maxDate');
|
||||||
|
|
||||||
|
return self::getAllByQuery($query, RelationType::ALL, 6);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,13 @@ return ['HumanResourceTimeRecording' => [
|
||||||
'CT3' => 'Vacation',
|
'CT3' => 'Vacation',
|
||||||
'CT4' => 'Sick',
|
'CT4' => 'Sick',
|
||||||
'CT5' => 'On the move',
|
'CT5' => 'On the move',
|
||||||
|
'D0' => 'Sunday',
|
||||||
|
'D1' => 'Monday',
|
||||||
|
'D2' => 'Tuesday',
|
||||||
|
'D3' => 'Wednesday',
|
||||||
|
'D4' => 'Thursday',
|
||||||
|
'D5' => 'Friday',
|
||||||
|
'D6' => 'Saturday',
|
||||||
'Date' => 'Date',
|
'Date' => 'Date',
|
||||||
'End' => 'End',
|
'End' => 'End',
|
||||||
'Recordings' => 'Recordings',
|
'Recordings' => 'Recordings',
|
||||||
|
|
|
||||||
|
|
@ -16,60 +16,20 @@ declare(strict_types=1);
|
||||||
use \Modules\HumanResourceTimeRecording\Models\ClockingType;
|
use \Modules\HumanResourceTimeRecording\Models\ClockingType;
|
||||||
use \Modules\HumanResourceTimeRecording\Models\ClockingStatus;
|
use \Modules\HumanResourceTimeRecording\Models\ClockingStatus;
|
||||||
|
|
||||||
|
$sessions = $this->getData('sessions');
|
||||||
|
|
||||||
echo $this->getData('nav')->render(); ?>
|
echo $this->getData('nav')->render(); ?>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4 col-xs-12">
|
<div class="col-xs-12">
|
||||||
<section class="box wf-100">
|
|
||||||
<div class="inner">
|
|
||||||
<form id="clocking" method="PUT" action="<?= \phpOMS\Uri\UriFactory::build('{/api}task/element?{?}&csrf={$CSRF}'); ?>">
|
|
||||||
<table class="layout wf-100" style="table-layout: fixed">
|
|
||||||
<tr><td><label for="iType"><?= $this->getHtml('Type') ?></label>
|
|
||||||
<tr><td>
|
|
||||||
<select id="iType" name="Type">
|
|
||||||
<option value="<?= ClockingType::OFFICE; ?>"><?= $this->getHtml('CT0') ?>
|
|
||||||
<option value="<?= ClockingType::REMOTE; ?>"><?= $this->getHtml('CT1') ?>
|
|
||||||
<option value="<?= ClockingType::HOME; ?>"><?= $this->getHtml('CT2') ?>
|
|
||||||
<option value="<?= ClockingType::VACATION; ?>"><?= $this->getHtml('CT3') ?>
|
|
||||||
<option value="<?= ClockingType::SICK; ?>"><?= $this->getHtml('CT4') ?>
|
|
||||||
<option value="<?= ClockingType::ON_THE_MOVE; ?>"><?= $this->getHtml('CT5') ?>
|
|
||||||
</select>
|
|
||||||
<tr><td><label for="iStatus"><?= $this->getHtml('Status') ?></label>
|
|
||||||
<tr><td>
|
|
||||||
<select id="iStatus" name="Status">
|
|
||||||
<option value="<?= ClockingStatus::START; ?>"><?= $this->getHtml('CS0') ?>
|
|
||||||
<option value="<?= ClockingStatus::PAUSE; ?>"><?= $this->getHtml('CS1') ?>
|
|
||||||
<option value="<?= ClockingStatus::CONTINUE; ?>"><?= $this->getHtml('CS2') ?>
|
|
||||||
<option value="<?= ClockingStatus::END; ?>"><?= $this->getHtml('CS3') ?>
|
|
||||||
</select>
|
|
||||||
<tr><td>
|
|
||||||
<input type="submit" id="iclockingButton" name="clockingButton" value="<?= $this->getHtml('Submit', '0', '0'); ?>">
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-4 col-xs-12">
|
|
||||||
<section class="box wf-100">
|
|
||||||
<header><h1>Vaction</h1></header>
|
|
||||||
<div class="inner">
|
|
||||||
<table>
|
|
||||||
<tr><td>Used Vacation<td>
|
|
||||||
<tr><td>Last Vacation<td>
|
|
||||||
<tr><td>Next Vacation<td>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-4 col-xs-12">
|
|
||||||
<div class="box wf-100">
|
<div class="box wf-100">
|
||||||
<table id="accountList" class="default">
|
<table id="accountList" class="default">
|
||||||
<caption><?= $this->getHtml('Recordings') ?><i class="fa fa-download floatRight download btn"></i></caption>
|
<caption><?= $this->getHtml('Recordings') ?><i class="fa fa-download floatRight download btn"></i></caption>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td><?= $this->getHtml('Date'); ?>
|
<td><?= $this->getHtml('Date'); ?>
|
||||||
|
<td>Status
|
||||||
|
<td>Employee
|
||||||
<td><?= $this->getHtml('Start') ?>
|
<td><?= $this->getHtml('Start') ?>
|
||||||
<td><?= $this->getHtml('Break') ?>
|
<td><?= $this->getHtml('Break') ?>
|
||||||
<td><?= $this->getHtml('End') ?>
|
<td><?= $this->getHtml('End') ?>
|
||||||
|
|
@ -77,17 +37,17 @@ echo $this->getData('nav')->render(); ?>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr><td colspan="5">
|
<tr><td colspan="5">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<?php foreach ($sessions as $session) : ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= $session->getStart()->format('Y-m-d'); ?>
|
||||||
|
<td><span class="tag">Status Here</span>
|
||||||
|
<td><?= $session->getEmployee()->getProfile()->getAccount()->getName1(); ?>, <?= $session->getEmployee()->getProfile()->getAccount()->getName2(); ?>
|
||||||
|
<td><?= $session->getStart()->format('H:i:s'); ?>
|
||||||
|
<td><?= (int) ($session->getBreak() / 3600); ?>h <?= ((int) ($session->getBreak() / 60) % 60); ?>m
|
||||||
|
<td><?= $session->getEnd() !== null ? $session->getEnd()->format('H:i') : ''; ?>
|
||||||
|
<td><?= (int) ($session->getBusy() / 3600); ?>h <?= ((int) ($session->getBusy() / 60) % 60); ?>m
|
||||||
|
<?php endforeach; ?>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
on response successfull reload!!! or!
|
|
||||||
on response successfull change ui/change ui and on response not successfull undo changed ui both result in the same
|
|
||||||
|
|
||||||
list for month show total of total
|
|
||||||
list contains segments for week show total of total
|
|
||||||
every week contains every day show total of total
|
|
||||||
if you click on a day you get detailed information of that day
|
|
||||||
|
|
||||||
show additional section with vacation days
|
|
||||||
120
Theme/Backend/private-dashboard.tpl.php
Normal file
120
Theme/Backend/private-dashboard.tpl.php
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package HumanResourceTimeRecording
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
use \Modules\HumanResourceTimeRecording\Models\ClockingType;
|
||||||
|
use \Modules\HumanResourceTimeRecording\Models\ClockingStatus;
|
||||||
|
|
||||||
|
$sessions = $this->getData('sessions');
|
||||||
|
|
||||||
|
echo $this->getData('nav')->render(); ?>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4 col-xs-12">
|
||||||
|
<section class="box wf-100">
|
||||||
|
<div class="inner">
|
||||||
|
<form id="clocking" method="PUT" action="<?= \phpOMS\Uri\UriFactory::build('{/api}task/element?{?}&csrf={$CSRF}'); ?>">
|
||||||
|
<table class="layout wf-100" style="table-layout: fixed">
|
||||||
|
<tr><td><label for="iType"><?= $this->getHtml('Type') ?></label>
|
||||||
|
<tr><td>
|
||||||
|
<select id="iType" name="Type">
|
||||||
|
<option value="<?= ClockingType::OFFICE; ?>"><?= $this->getHtml('CT0') ?>
|
||||||
|
<option value="<?= ClockingType::REMOTE; ?>"><?= $this->getHtml('CT1') ?>
|
||||||
|
<option value="<?= ClockingType::HOME; ?>"><?= $this->getHtml('CT2') ?>
|
||||||
|
<option value="<?= ClockingType::VACATION; ?>"><?= $this->getHtml('CT3') ?>
|
||||||
|
<option value="<?= ClockingType::SICK; ?>"><?= $this->getHtml('CT4') ?>
|
||||||
|
<option value="<?= ClockingType::ON_THE_MOVE; ?>"><?= $this->getHtml('CT5') ?>
|
||||||
|
</select>
|
||||||
|
<tr><td><label for="iStatus"><?= $this->getHtml('Status') ?></label>
|
||||||
|
<tr><td>
|
||||||
|
<select id="iStatus" name="Status">
|
||||||
|
<option value="<?= ClockingStatus::START; ?>"><?= $this->getHtml('CS0') ?>
|
||||||
|
<option value="<?= ClockingStatus::PAUSE; ?>"><?= $this->getHtml('CS1') ?>
|
||||||
|
<option value="<?= ClockingStatus::CONTINUE; ?>"><?= $this->getHtml('CS2') ?>
|
||||||
|
<option value="<?= ClockingStatus::END; ?>"><?= $this->getHtml('CS3') ?>
|
||||||
|
</select>
|
||||||
|
<tr><td>
|
||||||
|
<input type="submit" id="iclockingButton" name="clockingButton" value="<?= $this->getHtml('Submit', '0', '0'); ?>">
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4 col-xs-12">
|
||||||
|
<section class="box wf-100">
|
||||||
|
<header><h1>Work</h1></header>
|
||||||
|
<div class="inner">
|
||||||
|
<table>
|
||||||
|
<tr><td>This month<td>
|
||||||
|
<tr><td>Last month<td>
|
||||||
|
<tr><td>This year<td>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4 col-xs-12">
|
||||||
|
<section class="box wf-100">
|
||||||
|
<header><h1>Vaction</h1></header>
|
||||||
|
<div class="inner">
|
||||||
|
<table>
|
||||||
|
<tr><td>Used Vacation<td>
|
||||||
|
<tr><td>Last Vacation<td>
|
||||||
|
<tr><td>Next Vacation<td>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<div class="box wf-100">
|
||||||
|
<table id="accountList" class="default">
|
||||||
|
<caption><?= $this->getHtml('Recordings') ?><i class="fa fa-download floatRight download btn"></i></caption>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td><?= $this->getHtml('Date'); ?>
|
||||||
|
<td>Status
|
||||||
|
<td><?= $this->getHtml('Start') ?>
|
||||||
|
<td><?= $this->getHtml('Break') ?>
|
||||||
|
<td><?= $this->getHtml('End') ?>
|
||||||
|
<td><?= $this->getHtml('Total') ?>
|
||||||
|
<tfoot>
|
||||||
|
<tr><td colspan="5">
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($sessions as $session) : ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= $session->getStart()->format('Y-m-d'); ?> - <?= $this->getHtml('D' . $session->getStart()->format('w')); ?>
|
||||||
|
<td><span class="tag">Status Here</span>
|
||||||
|
<td><?= $session->getStart()->format('H:i'); ?>
|
||||||
|
<td><?= (int) ($session->getBreak() / 3600); ?>h <?= ((int) ($session->getBreak() / 60) % 60); ?>m
|
||||||
|
<td><?= $session->getEnd() !== null ? $session->getEnd()->format('H:i') : ''; ?>
|
||||||
|
<td><?= (int) ($session->getBusy() / 3600); ?>h <?= ((int) ($session->getBusy() / 60) % 60); ?>m
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
on response successfull reload!!! or!
|
||||||
|
on response successfull change ui/change ui and on response not successfull undo changed ui both result in the same
|
||||||
|
|
||||||
|
list for month show total of total
|
||||||
|
list contains segments for week show total of total
|
||||||
|
every week contains every day show total of total
|
||||||
|
if you click on a day you get detailed information of that day
|
||||||
|
|
||||||
|
show additional section with vacation days
|
||||||
Loading…
Reference in New Issue
Block a user