mirror of
https://github.com/Karaka-Management/oms-HumanResourceTimeRecording.git
synced 2026-01-11 11:58:47 +00:00
bug fixes
This commit is contained in:
parent
492eb38e22
commit
1e0a52edad
2
.github/workflows/greetings.yml
vendored
2
.github/workflows/greetings.yml
vendored
|
|
@ -9,5 +9,5 @@ jobs:
|
|||
- uses: actions/first-interaction@v1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-message: 'Thank you for createing this issue. We will check it as soon as possible.'
|
||||
issue-message: 'Thank you for creating this issue. We will check it as soon as possible.'
|
||||
pr-message: 'Thank you for your pull request. We will check it as soon as possible.'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,73 @@
|
|||
{
|
||||
"hr_timerecording_type": {
|
||||
"name": "hr_timerecording_type",
|
||||
"fields": {
|
||||
"hr_timerecording_type_id": {
|
||||
"name": "hr_timerecording_type_id",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"primary": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"hr_timerecording_type_name": {
|
||||
"name": "hr_timerecording_type_name",
|
||||
"type": "VARCHAR(50)",
|
||||
"null": false
|
||||
},
|
||||
"hr_timerecording_type_custom_future": {
|
||||
"name": "hr_timerecording_type_custom_future",
|
||||
"type": "TINYINT(1)",
|
||||
"null": false
|
||||
},
|
||||
"hr_timerecording_type_custom_past": {
|
||||
"name": "hr_timerecording_type_custom_past",
|
||||
"type": "TINYINT(1)",
|
||||
"null": false
|
||||
},
|
||||
"hr_timerecording_type_correction": {
|
||||
"name": "hr_timerecording_type_correction",
|
||||
"type": "TINYINT(1)",
|
||||
"null": false
|
||||
},
|
||||
"hr_timerecording_type_work": {
|
||||
"name": "hr_timerecording_type_work",
|
||||
"type": "TINYINT(1)",
|
||||
"null": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"hr_timerecording_type_l11n": {
|
||||
"name": "hr_timerecording_type_l11n",
|
||||
"fields": {
|
||||
"hr_timerecording_type_l11n_id": {
|
||||
"name": "hr_timerecording_type_l11n_id",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"primary": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"hr_timerecording_type_l11n_title": {
|
||||
"name": "hr_timerecording_type_l11n_title",
|
||||
"type": "VARCHAR(255)",
|
||||
"null": false
|
||||
},
|
||||
"hr_timerecording_type_l11n_type": {
|
||||
"name": "hr_timerecording_type_l11n_type",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"foreignTable": "hr_timerecording_type",
|
||||
"foreignKey": "hr_timerecording_type_id"
|
||||
},
|
||||
"hr_timerecording_type_l11n_language": {
|
||||
"name": "hr_timerecording_type_l11n_language",
|
||||
"type": "VARCHAR(2)",
|
||||
"default": null,
|
||||
"null": true,
|
||||
"foreignTable": "language",
|
||||
"foreignKey": "language_639_1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"hr_timerecording_session": {
|
||||
"name": "hr_timerecording_session",
|
||||
"fields": {
|
||||
|
|
@ -11,8 +80,10 @@
|
|||
},
|
||||
"hr_timerecording_session_type": {
|
||||
"name": "hr_timerecording_session_type",
|
||||
"type": "TINYINT",
|
||||
"null": false
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"foreignTable": "hr_timerecording_type",
|
||||
"foreignKey": "hr_timerecording_type_id"
|
||||
},
|
||||
"hr_timerecording_session_start": {
|
||||
"name": "hr_timerecording_session_start",
|
||||
|
|
|
|||
121
Admin/Install/types.json
Normal file
121
Admin/Install/types.json
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
[
|
||||
{
|
||||
"name": "office",
|
||||
"is_work": true,
|
||||
"l11n": {
|
||||
"en": "Office",
|
||||
"de": "Büro"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "home",
|
||||
"is_work": true,
|
||||
"l11n": {
|
||||
"en": "Home",
|
||||
"de": "Zuhause"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "remote",
|
||||
"is_work": true,
|
||||
"l11n": {
|
||||
"en": "Remote",
|
||||
"de": "Mobil"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "vacation",
|
||||
"is_work": false,
|
||||
"l11n": {
|
||||
"en": "Vacation",
|
||||
"de": "Urlaub"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "sick",
|
||||
"l11n": {
|
||||
"en": "Sick",
|
||||
"de": "Krank"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "travelling",
|
||||
"is_work": true,
|
||||
"l11n": {
|
||||
"en": "Travelling",
|
||||
"de": "Dienstreise"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "paid_leave",
|
||||
"is_work": false,
|
||||
"l11n": {
|
||||
"en": "Paid leave",
|
||||
"de": "Bezahlte Abwesenheit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "unpaid_leave",
|
||||
"is_work": false,
|
||||
"l11n": {
|
||||
"en": "Unpaid leave",
|
||||
"de": "Unbezahlte Abwesenheit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "maternity_leave",
|
||||
"is_work": false,
|
||||
"l11n": {
|
||||
"en": "Maternity leave",
|
||||
"de": "Mutterschutzurlaub"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "parental_leave",
|
||||
"is_work": false,
|
||||
"l11n": {
|
||||
"en": "Parental leave",
|
||||
"de": "Elternzeit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dr_visit",
|
||||
"is_work": false,
|
||||
"l11n": {
|
||||
"en": "Dr visit",
|
||||
"de": "Arztbesuch"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "education",
|
||||
"is_work": true,
|
||||
"l11n": {
|
||||
"en": "Education",
|
||||
"de": "Fortbildung"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "training",
|
||||
"is_work": true,
|
||||
"l11n": {
|
||||
"en": "Training",
|
||||
"de": "Training"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "holiday",
|
||||
"is_work": true,
|
||||
"l11n": {
|
||||
"en": "Holiday",
|
||||
"de": "Feiertag"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "no_data",
|
||||
"is_work": false,
|
||||
"l11n": {
|
||||
"en": "No data",
|
||||
"de": "Keine Daten"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -14,7 +14,12 @@ declare(strict_types=1);
|
|||
|
||||
namespace Modules\HumanResourceTimeRecording\Admin;
|
||||
|
||||
use phpOMS\Application\ApplicationAbstract;
|
||||
use phpOMS\Config\SettingsInterface;
|
||||
use phpOMS\Message\Http\HttpRequest;
|
||||
use phpOMS\Message\Http\HttpResponse;
|
||||
use phpOMS\Module\InstallerAbstract;
|
||||
use phpOMS\Module\ModuleInfo;
|
||||
|
||||
/**
|
||||
* Installer class.
|
||||
|
|
@ -33,4 +38,88 @@ final class Installer extends InstallerAbstract
|
|||
* @since 1.0.0
|
||||
*/
|
||||
public const PATH = __DIR__;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function install(ApplicationAbstract $app, ModuleInfo $info, SettingsInterface $cfgHandler) : void
|
||||
{
|
||||
parent::install($app, $info, $cfgHandler);
|
||||
|
||||
/* Clocking types */
|
||||
$fileContent = \file_get_contents(__DIR__ . '/Install/types.json');
|
||||
if ($fileContent === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var array $types */
|
||||
$types = \json_decode($fileContent, true);
|
||||
if ($types === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::createClockingTypes($app, $types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Install default bill types
|
||||
*
|
||||
* @param ApplicationAbstract $app Application
|
||||
* @param array $types Clocking types
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createClockingTypes(ApplicationAbstract $app, array $types) : array
|
||||
{
|
||||
$billTypes = [];
|
||||
|
||||
/** @var \Modules\HumanResourceTimeRecording\Controller\ApiClockingTypeController $module */
|
||||
$module = $app->moduleManager->get('HumanResourceTimeRecording', 'ApiClockingType');
|
||||
|
||||
foreach ($types as $type) {
|
||||
$response = new HttpResponse();
|
||||
$request = new HttpRequest();
|
||||
|
||||
$request->header->account = 1;
|
||||
$request->setData('name', $type['name'] ?? '');
|
||||
$request->setData('is_work', $type['is_work'] ?? false);
|
||||
$request->setData('title', \reset($type['l11n']));
|
||||
$request->setData('language', \array_keys($type['l11n'])[0] ?? 'en');
|
||||
|
||||
$module->apiClockingTypeCreate($request, $response);
|
||||
|
||||
$responseData = $response->getData('');
|
||||
if (!\is_array($responseData)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$billType = \is_array($responseData['response'])
|
||||
? $responseData['response']
|
||||
: $responseData['response']->toArray();
|
||||
|
||||
$billTypes[] = $billType;
|
||||
|
||||
$isFirst = true;
|
||||
foreach ($type['l11n'] as $language => $l11n) {
|
||||
if ($isFirst) {
|
||||
$isFirst = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
$response = new HttpResponse();
|
||||
$request = new HttpRequest();
|
||||
|
||||
$request->header->account = 1;
|
||||
$request->setData('title', $l11n);
|
||||
$request->setData('language', $language);
|
||||
$request->setData('type', $billType['id']);
|
||||
|
||||
$module->apiClockingTypeL11nCreate($request, $response);
|
||||
}
|
||||
}
|
||||
|
||||
return $billTypes;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
405
Controller/ApiClockingTypeController.php
Normal file
405
Controller/ApiClockingTypeController.php
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Jingga
|
||||
*
|
||||
* PHP Version 8.2
|
||||
*
|
||||
* @package Modules\HumanResourceTimeRecording
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\HumanResourceTimeRecording\Controller;
|
||||
|
||||
use Modules\HumanResourceTimeRecording\Models\ClockingType;
|
||||
use Modules\HumanResourceTimeRecording\Models\ClockingTypeL11nMapper;
|
||||
use Modules\HumanResourceTimeRecording\Models\ClockingTypeMapper;
|
||||
use phpOMS\Localization\BaseStringL11n;
|
||||
use phpOMS\Localization\ISO639x1Enum;
|
||||
use phpOMS\Message\Http\RequestStatusCode;
|
||||
use phpOMS\Message\RequestAbstract;
|
||||
use phpOMS\Message\ResponseAbstract;
|
||||
|
||||
/**
|
||||
* HumanResourceTimeRecording class.
|
||||
*
|
||||
* @package Modules\HumanResourceTimeRecording
|
||||
* @license OMS License 2.0
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class ApiClockingTypeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Api method to create clocking type
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param array $data Generic data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiClockingTypeCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
|
||||
{
|
||||
if (!empty($val = $this->validateClockingTypeCreate($request))) {
|
||||
$response->header->status = RequestStatusCode::R_400;
|
||||
$this->createInvalidCreateResponse($request, $response, $val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$clockingType = $this->createClockingTypeFromRequest($request);
|
||||
$this->createModel($request->header->account, $clockingType, ClockingTypeMapper::class, 'clocking_type', $request->getOrigin());
|
||||
$this->createStandardCreateResponse($request, $response, $clockingType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to create ClockingType from request.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return ClockingType
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function createClockingTypeFromRequest(RequestAbstract $request) : ClockingType
|
||||
{
|
||||
$clockingType = new ClockingType($request->getDataString('name') ?? '');
|
||||
$clockingType->isWork = $request->getDataBool('is_work') ?? false;
|
||||
$clockingType->customFutureTimeAllowed = $request->getDataBool('custom_future_time_allowed') ?? false;
|
||||
$clockingType->customPastTimeAllowed = $request->getDataBool('custom_past_time_allowed') ?? false;
|
||||
$clockingType->correctionAllowed = $request->getDataBool('correction_allowed') ?? false;
|
||||
$clockingType->setL11n(
|
||||
$request->getDataString('title') ?? '',
|
||||
ISO639x1Enum::tryFromValue($request->getDataString('language')) ?? ISO639x1Enum::_EN
|
||||
);
|
||||
|
||||
return $clockingType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ClockingType create request
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return array<string, bool>
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function validateClockingTypeCreate(RequestAbstract $request) : array
|
||||
{
|
||||
$val = [];
|
||||
if (($val['title'] = !$request->hasData('title'))
|
||||
|| ($val['name'] = !$request->hasData('name'))
|
||||
) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to create ClockingType l11n
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param array $data Generic data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiClockingTypeL11nCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
|
||||
{
|
||||
if (!empty($val = $this->validateClockingTypeL11nCreate($request))) {
|
||||
$response->header->status = RequestStatusCode::R_400;
|
||||
$this->createInvalidCreateResponse($request, $response, $val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$clockingTypeL11n = $this->createClockingTypeL11nFromRequest($request);
|
||||
$this->createModel($request->header->account, $clockingTypeL11n, ClockingTypeL11nMapper::class, 'clocking_type_l11n', $request->getOrigin());
|
||||
$this->createStandardCreateResponse($request, $response, $clockingTypeL11n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to create ClockingType l11n from request.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return BaseStringL11n
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function createClockingTypeL11nFromRequest(RequestAbstract $request) : BaseStringL11n
|
||||
{
|
||||
$clockingTypeL11n = new BaseStringL11n();
|
||||
$clockingTypeL11n->ref = $request->getDataInt('type') ?? 0;
|
||||
$clockingTypeL11n->language = ISO639x1Enum::tryFromValue($request->getDataString('language')) ?? $request->header->l11n->language;
|
||||
$clockingTypeL11n->content = $request->getDataString('title') ?? '';
|
||||
|
||||
return $clockingTypeL11n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ClockingType l11n create request
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return array<string, bool>
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function validateClockingTypeL11nCreate(RequestAbstract $request) : array
|
||||
{
|
||||
$val = [];
|
||||
if (($val['title'] = !$request->hasData('title'))
|
||||
|| ($val['type'] = !$request->hasData('type'))
|
||||
) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to update ClockingType
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param array $data Generic data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiClockingTypeUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
|
||||
{
|
||||
if (!empty($val = $this->validateClockingTypeUpdate($request))) {
|
||||
$response->header->status = RequestStatusCode::R_400;
|
||||
$this->createInvalidUpdateResponse($request, $response, $val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var ClockingType $old */
|
||||
$old = ClockingTypeMapper::get()->where('id', (int) $request->getData('id'));
|
||||
$new = $this->updateClockingTypeFromRequest($request, clone $old);
|
||||
|
||||
$this->updateModel($request->header->account, $old, $new, ClockingTypeMapper::class, 'clocking_type', $request->getOrigin());
|
||||
$this->createStandardUpdateResponse($request, $response, $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update ClockingType from request.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ClockingType $new Model to modify
|
||||
*
|
||||
* @return ClockingType
|
||||
*
|
||||
* @todo Implement API update function
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function updateClockingTypeFromRequest(RequestAbstract $request, ClockingType $new) : ClockingType
|
||||
{
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ClockingType update request
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return array<string, bool>
|
||||
*
|
||||
* @todo Implement API validation function
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function validateClockingTypeUpdate(RequestAbstract $request) : array
|
||||
{
|
||||
$val = [];
|
||||
if (($val['id'] = !$request->hasData('id'))) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to delete ClockingType
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param array $data Generic data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiClockingTypeDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
|
||||
{
|
||||
if (!empty($val = $this->validateClockingTypeDelete($request))) {
|
||||
$response->header->status = RequestStatusCode::R_400;
|
||||
$this->createInvalidDeleteResponse($request, $response, $val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var \Modules\HumanResourceTimeRecording\Models\ClockingType $clockingType */
|
||||
$clockingType = ClockingTypeMapper::get()->where('id', (int) $request->getData('id'))->execute();
|
||||
$this->deleteModel($request->header->account, $clockingType, ClockingTypeMapper::class, 'clocking_type', $request->getOrigin());
|
||||
$this->createStandardDeleteResponse($request, $response, $clockingType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ClockingType delete request
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return array<string, bool>
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function validateClockingTypeDelete(RequestAbstract $request) : array
|
||||
{
|
||||
$val = [];
|
||||
if (($val['id'] = !$request->hasData('id'))) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to update ClockingTypeL11n
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param array $data Generic data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiClockingTypeL11nUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
|
||||
{
|
||||
if (!empty($val = $this->validateClockingTypeL11nUpdate($request))) {
|
||||
$response->header->status = RequestStatusCode::R_400;
|
||||
$this->createInvalidUpdateResponse($request, $response, $val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var BaseStringL11n $old */
|
||||
$old = ClockingTypeL11nMapper::get()->where('id', (int) $request->getData('id'));
|
||||
$new = $this->updateClockingTypeL11nFromRequest($request, clone $old);
|
||||
|
||||
$this->updateModel($request->header->account, $old, $new, ClockingTypeL11nMapper::class, 'clocking_type_l11n', $request->getOrigin());
|
||||
$this->createStandardUpdateResponse($request, $response, $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update ClockingTypeL11n from request.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param BaseStringL11n $new Model to modify
|
||||
*
|
||||
* @return BaseStringL11n
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function updateClockingTypeL11nFromRequest(RequestAbstract $request, BaseStringL11n $new) : BaseStringL11n
|
||||
{
|
||||
$new->ref = $request->getDataInt('type') ?? $new->ref;
|
||||
$new->language = ISO639x1Enum::tryFromValue($request->getDataString('language')) ?? $new->language;
|
||||
$new->content = $request->getDataString('title') ?? $new->content;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ClockingTypeL11n update request
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return array<string, bool>
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function validateClockingTypeL11nUpdate(RequestAbstract $request) : array
|
||||
{
|
||||
$val = [];
|
||||
if (($val['id'] = !$request->hasData('id'))) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to delete ClockingTypeL11n
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param array $data Generic data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiClockingTypeL11nDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
|
||||
{
|
||||
if (!empty($val = $this->validateClockingTypeL11nDelete($request))) {
|
||||
$response->header->status = RequestStatusCode::R_400;
|
||||
$this->createInvalidDeleteResponse($request, $response, $val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var BaseStringL11n $clockingTypeL11n */
|
||||
$clockingTypeL11n = ClockingTypeL11nMapper::get()->where('id', (int) $request->getData('id'))->execute();
|
||||
$this->deleteModel($request->header->account, $clockingTypeL11n, ClockingTypeL11nMapper::class, 'clocking_type_l11n', $request->getOrigin());
|
||||
$this->createStandardDeleteResponse($request, $response, $clockingTypeL11n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ClockingTypeL11n delete request
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return array<string, bool>
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function validateClockingTypeL11nDelete(RequestAbstract $request) : array
|
||||
{
|
||||
$val = [];
|
||||
if (($val['id'] = !$request->hasData('id'))) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ use Modules\Admin\Models\NullAccount;
|
|||
use Modules\HumanResourceManagement\Models\EmployeeMapper;
|
||||
use Modules\HumanResourceTimeRecording\Models\ClockingStatus;
|
||||
use Modules\HumanResourceTimeRecording\Models\ClockingType;
|
||||
use Modules\HumanResourceTimeRecording\Models\NullClockingType;
|
||||
use Modules\HumanResourceTimeRecording\Models\PermissionCategory;
|
||||
use Modules\HumanResourceTimeRecording\Models\Session;
|
||||
use Modules\HumanResourceTimeRecording\Models\SessionElement;
|
||||
|
|
@ -55,7 +56,9 @@ final class ApiController extends Controller
|
|||
*/
|
||||
public function apiSessionCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
|
||||
{
|
||||
if (!$this->app->accountManager->get($request->header->account)->hasPermission(
|
||||
if ($request->hasData('account')
|
||||
&& $request->getDataInt('account') !== $request->header->account
|
||||
&& !$this->app->accountManager->get($request->header->account)->hasPermission(
|
||||
PermissionType::CREATE, $this->app->unitId, $this->app->appId, self::NAME, PermissionCategory::SESSION_FOREIGN
|
||||
)) {
|
||||
$response->header->status = RequestStatusCode::R_403;
|
||||
|
|
@ -95,10 +98,11 @@ final class ApiController extends Controller
|
|||
$account = $request->getDataInt('account') ?? $request->header->account;
|
||||
|
||||
$session = new Session(new NullAccount($account));
|
||||
$session->type = ClockingType::tryFromValue($request->getDataInt('type')) ?? ClockingType::OFFICE;
|
||||
$session->type = new NullClockingType((int) $request->getDataInt('type'));
|
||||
|
||||
// a custom datetime can only be set if the user is allowed to create a session for a foreign account or if the session is a vacation
|
||||
$dt = $request->hasData('account') || $session->type === ClockingType::VACATION
|
||||
// @security check if custom datetime is allowed to be set
|
||||
|
||||
$dt = $request->hasData('account')
|
||||
? ($request->getDataDateTime('datetime') ?? new \DateTime('now'))
|
||||
: new \DateTime('now');
|
||||
|
||||
|
|
@ -208,8 +212,7 @@ final class ApiController extends Controller
|
|||
return null;
|
||||
}
|
||||
|
||||
// a custom datetime can only be set if the user is allowed to create a session for a foreign account or if the session is a vacation
|
||||
$dt = $request->hasData('account') || $session->type === ClockingType::VACATION
|
||||
$dt = $request->hasData('account')
|
||||
? ($request->getDataDateTime('datetime') ?? new \DateTime('now'))
|
||||
: new \DateTime('now');
|
||||
|
||||
|
|
|
|||
|
|
@ -14,48 +14,111 @@ declare(strict_types=1);
|
|||
|
||||
namespace Modules\HumanResourceTimeRecording\Models;
|
||||
|
||||
use phpOMS\Stdlib\Base\Enum;
|
||||
use Modules\Media\Models\Collection;
|
||||
use phpOMS\Localization\BaseStringL11n;
|
||||
use phpOMS\Localization\ISO639x1Enum;
|
||||
|
||||
/**
|
||||
* ClockingType enum.
|
||||
* Bill type enum.
|
||||
*
|
||||
* @package Modules\HumanResourceTimeRecording\Models
|
||||
* @license OMS License 2.0
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @todo Make ClockingTypes a DB model instead of an enum
|
||||
* https://github.com/Karaka-Management/oms-HumanResourceTimeRecording/issues/16
|
||||
*/
|
||||
abstract class ClockingType extends Enum
|
||||
class ClockingType implements \JsonSerializable
|
||||
{
|
||||
public const OFFICE = 1;
|
||||
/**
|
||||
* Id
|
||||
*
|
||||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $id = 0;
|
||||
|
||||
public const HOME = 2;
|
||||
public string $name = '';
|
||||
|
||||
public const REMOTE = 3;
|
||||
public bool $customFutureTimeAllowed = false;
|
||||
|
||||
public const VACATION = 4;
|
||||
public bool $customPastTimeAllowed = false;
|
||||
|
||||
public const SICK = 5;
|
||||
public bool $correctionAllowed = false;
|
||||
|
||||
public const ON_THE_MOVE = 6;
|
||||
public bool $isWork = true;
|
||||
|
||||
public const PAID_LEAVE = 7;
|
||||
/**
|
||||
* Localization
|
||||
*
|
||||
* @var string|BaseStringL11n
|
||||
*/
|
||||
public string | BaseStringL11n $l11n;
|
||||
|
||||
public const UNPAID_LEAVE = 8;
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name Name
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(string $name = '')
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public const MATERNITY_LEAVE = 9;
|
||||
/**
|
||||
* Set l11n
|
||||
*
|
||||
* @param string|BaseStringL11n $l11n Tag article l11n
|
||||
* @param string $lang Language
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setL11n(string | BaseStringL11n $l11n, string $lang = ISO639x1Enum::_EN) : void
|
||||
{
|
||||
if ($l11n instanceof BaseStringL11n) {
|
||||
$this->l11n = $l11n;
|
||||
} elseif (isset($this->l11n) && $this->l11n instanceof BaseStringL11n) {
|
||||
$this->l11n->content = $l11n;
|
||||
$this->l11n->language = $lang;
|
||||
} else {
|
||||
$this->l11n = new BaseStringL11n();
|
||||
$this->l11n->content = $l11n;
|
||||
$this->l11n->ref = $this->id;
|
||||
$this->l11n->language = $lang;
|
||||
}
|
||||
}
|
||||
|
||||
public const PARENTAL_LEAVE = 10;
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getL11n() : string
|
||||
{
|
||||
if (!isset($this->l11n)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
public const DR_VISIT = 11;
|
||||
return $this->l11n instanceof BaseStringL11n ? $this->l11n->content : $this->l11n;
|
||||
}
|
||||
|
||||
public const EDUCATION = 12;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toArray() : array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
];
|
||||
}
|
||||
|
||||
public const TRAINING = 13;
|
||||
|
||||
public const HOLIDAY = 14;
|
||||
|
||||
public const NO_DATA = -1;
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize() : mixed
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
69
Models/ClockingTypeL11nMapper.php
Normal file
69
Models/ClockingTypeL11nMapper.php
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
/**
|
||||
* Jingga
|
||||
*
|
||||
* PHP Version 8.2
|
||||
*
|
||||
* @package Modules\HumanResourceTimerecording\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\HumanResourceTimerecording\Models;
|
||||
|
||||
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||
use phpOMS\Localization\BaseStringL11n;
|
||||
|
||||
/**
|
||||
* Clocking type l11n mapper class.
|
||||
*
|
||||
* @package Modules\HumanResourceTimerecording\Models
|
||||
* @license OMS License 2.0
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @template T of BaseStringL11n
|
||||
* @extends DataMapperFactory<T>
|
||||
*/
|
||||
final class ClockingTypeL11nMapper extends DataMapperFactory
|
||||
{
|
||||
/**
|
||||
* Columns.
|
||||
*
|
||||
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const COLUMNS = [
|
||||
'hr_timerecording_type_l11n_id' => ['name' => 'hr_timerecording_type_l11n_id', 'type' => 'int', 'internal' => 'id'],
|
||||
'hr_timerecording_type_l11n_title' => ['name' => 'hr_timerecording_type_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true],
|
||||
'hr_timerecording_type_l11n_type' => ['name' => 'hr_timerecording_type_l11n_type', 'type' => 'int', 'internal' => 'ref'],
|
||||
'hr_timerecording_type_l11n_language' => ['name' => 'hr_timerecording_type_l11n_language', 'type' => 'string', 'internal' => 'language'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const TABLE = 'hr_timerecording_type_l11n';
|
||||
|
||||
/**
|
||||
* Primary field name.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const PRIMARYFIELD = 'hr_timerecording_type_l11n_id';
|
||||
|
||||
/**
|
||||
* Model to use by the mapper.
|
||||
*
|
||||
* @var class-string<T>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const MODEL = BaseStringL11n::class;
|
||||
}
|
||||
86
Models/ClockingTypeMapper.php
Normal file
86
Models/ClockingTypeMapper.php
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
/**
|
||||
* Jingga
|
||||
*
|
||||
* PHP Version 8.2
|
||||
*
|
||||
* @package Modules\HumanResourceTimeRecording\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\HumanResourceTimeRecording\Models;
|
||||
|
||||
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
|
||||
|
||||
/**
|
||||
* Clocking type mapper class.
|
||||
*
|
||||
* @package Modules\HumanResourceTimeRecording\Models
|
||||
* @license OMS License 2.0
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @template T of ClockingType
|
||||
* @extends DataMapperFactory<T>
|
||||
*/
|
||||
final class ClockingTypeMapper extends DataMapperFactory
|
||||
{
|
||||
/**
|
||||
* Columns.
|
||||
*
|
||||
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const COLUMNS = [
|
||||
'hr_timerecording_type_id' => ['name' => 'hr_timerecording_type_id', 'type' => 'int', 'internal' => 'id'],
|
||||
'hr_timerecording_type_name' => ['name' => 'hr_timerecording_type_name', 'type' => 'string', 'internal' => 'name'],
|
||||
'hr_timerecording_type_custom_future' => ['name' => 'hr_timerecording_type_custom_future', 'type' => 'bool', 'internal' => 'customFutureTimeAllowed'],
|
||||
'hr_timerecording_type_custom_past' => ['name' => 'hr_timerecording_type_custom_past', 'type' => 'bool', 'internal' => 'customPastTimeAllowed'],
|
||||
'hr_timerecording_type_correction' => ['name' => 'hr_timerecording_type_correction', 'type' => 'bool', 'internal' => 'correctionAllowed'],
|
||||
'hr_timerecording_type_work' => ['name' => 'hr_timerecording_type_work', 'type' => 'bool', 'internal' => 'isWork'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Has many relation.
|
||||
*
|
||||
* @var array<string, array{mapper:class-string, table:string, self?:?string, external?:?string, column?:string}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const HAS_MANY = [
|
||||
'l11n' => [
|
||||
'mapper' => ClockingTypeL11nMapper::class,
|
||||
'table' => 'hr_timerecording_type_l11n',
|
||||
'self' => 'hr_timerecording_type_l11n_type',
|
||||
'column' => 'content',
|
||||
'external' => null,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Model to use by the mapper.
|
||||
*
|
||||
* @var class-string<T>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const MODEL = ClockingType::class;
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const TABLE = 'hr_timerecording_type';
|
||||
|
||||
/**
|
||||
* Primary field name.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const PRIMARYFIELD = 'hr_timerecording_type_id';
|
||||
}
|
||||
47
Models/NullClockingType.php
Normal file
47
Models/NullClockingType.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
/**
|
||||
* Jingga
|
||||
*
|
||||
* PHP Version 8.2
|
||||
*
|
||||
* @package Modules\HumanResourceTimeRecording\Models
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\HumanResourceTimeRecording\Models;
|
||||
|
||||
/**
|
||||
* Null model
|
||||
*
|
||||
* @package Modules\HumanResourceTimeRecording\Models
|
||||
* @license OMS License 2.0
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class NullClockingType extends ClockingType
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $id Model id
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(int $id = 0)
|
||||
{
|
||||
$this->id = $id;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize() : mixed
|
||||
{
|
||||
return ['id' => $this->id];
|
||||
}
|
||||
}
|
||||
|
|
@ -69,7 +69,7 @@ class Session implements \JsonSerializable
|
|||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $type = ClockingType::NO_DATA;
|
||||
public ClockingType $type;
|
||||
|
||||
/**
|
||||
* Session elements.
|
||||
|
|
@ -107,6 +107,7 @@ class Session implements \JsonSerializable
|
|||
$this->start = new \DateTime('now');
|
||||
$this->employee = $employee ?? new NullAccount();
|
||||
$this->createdAt = new \DateTimeImmutable('now');
|
||||
$this->type = new NullClockingType();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -76,6 +76,19 @@ final class SessionMapper extends DataMapperFactory
|
|||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Has one relation.
|
||||
*
|
||||
* @var array<string, array{mapper:class-string, external:string, by?:string, column?:string, conditional?:bool}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public const OWNS_ONE = [
|
||||
'type' => [
|
||||
'mapper' => ClockingTypeMapper::class,
|
||||
'external' => 'hr_timerecording_session_type',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user