diff --git a/Admin/Install/db.json b/Admin/Install/db.json index d670e68..95b8eda 100644 --- a/Admin/Install/db.json +++ b/Admin/Install/db.json @@ -15,6 +15,11 @@ "null": false, "foreignTable": "account", "foreignKey": "account_id" + }, + "hr_staff_smiPHash": { + "name": "hr_staff_smiPHash", + "type": "VARCHAR(256)", + "null": false } } }, diff --git a/Admin/Routes/Web/Api.php b/Admin/Routes/Web/Api.php index fab8df7..2c3d3f6 100644 --- a/Admin/Routes/Web/Api.php +++ b/Admin/Routes/Web/Api.php @@ -8,7 +8,7 @@ use phpOMS\Router\RouteVerb; return [ '^.*/humanresource/staff.*$' => [ [ - 'dest' => '\Modules\HumanResourceManagement\Controller\ApiController:apiEmployeeFromAccountCreate', + 'dest' => '\Modules\HumanResourceManagement\Controller\ApiController:apiEmployeeCreate', 'verb' => RouteVerb::PUT, 'permission' => [ 'module' => ApiController::MODULE_NAME, diff --git a/Controller/ApiController.php b/Controller/ApiController.php index a168c1f..c3e4f52 100644 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -19,13 +19,14 @@ use Modules\HumanResourceManagement\Models\EmployeeMapper; use Modules\HumanResourceManagement\Models\EmployeeHistory; use Modules\HumanResourceManagement\Models\EmployeeHistoryMapper; -use phpOMS\Account\Account; use phpOMS\Localization\ISO639x1Enum; use phpOMS\Message\NotificationLevel; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; use phpOMS\Model\Message\FormValidation; use phpOMS\Utils\Parser\Markdown\Markdown; +use Modules\Admin\Models\Account; +use Modules\Profile\Models\Profile; /** * HumanResourceManagement controller class. @@ -37,6 +38,28 @@ use phpOMS\Utils\Parser\Markdown\Markdown; */ final class ApiController extends Controller { + /** + * Api method to create an employee from an existing account + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiEmployeeCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void + { + if ($request->getData('accounts') !== null) { + $this->apiEmployeeFromAccountCreate($request, $response, $data); + } + + $this->apiEmployeeNewCreate($request, $response, $data); + } + /** * Api method to create an employee from an existing account * @@ -58,9 +81,9 @@ final class ApiController extends Controller return; } - $employee = $this->createEmployeeFromAccountFromRequest($request); - $this->createModel($request->getHeader()->getAccount(), $employee, EmployeeMapper::class, 'employee'); - $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Employee', 'Employee successfully created', $employee); + $employees = $this->createEmployeeFromAccountFromRequest($request); + $this->createModels($request->getHeader()->getAccount(), $employees, EmployeeMapper::class, 'employee'); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Employee', 'Employee(s) successfully created', $employees); } /** @@ -75,8 +98,7 @@ final class ApiController extends Controller private function validateEmployeeFromAccountCreate(RequestAbstract $request) : array { $val = []; - if (($val['account'] = empty($request->getData('account'))) - ) { + if (($val['account'] = empty($request->getData('account')))) { return $val; } @@ -88,14 +110,91 @@ final class ApiController extends Controller * * @param RequestAbstract $request Request * + * @return Employee[] + * + * @since 1.0.0 + */ + private function createEmployeeFromAccountFromRequest(RequestAbstract $request) : array + { + $accounts = $request->getData('cc') ?? []; + if (!\is_array($accounts)) { + $accounts = [$accounts]; + } + + $employees = []; + foreach ($accounts as $account) { + $employees[] = new Employee((int) $account); + } + + return $employees; + } + + /** + * Api method to create a new employee + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiEmployeeNewCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void + { + if (!empty($val = $this->validateEmployeeNewCreate($request))) { + $response->set('employee_create', new FormValidation($val)); + + return; + } + + $employee = $this->createEmployeeNewFromRequest($request); + $this->createModel($request->getHeader()->getAccount(), $employee, EmployeeMapper::class, 'employee'); + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Employee', 'Employee successfully created', $employee); + } + + /** + * Validate employee create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateEmployeeNewCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['name1'] = empty($request->getData('name1')))) { + return $val; + } + + return []; + } + + /** + * Method to create a new employee from request. + * + * @param RequestAbstract $request Request + * * @return Employee * * @since 1.0.0 */ - private function createEmployeeFromAccountFromRequest(RequestAbstract $request) : Employee + private function createEmployeeNewFromRequest(RequestAbstract $request) : Employee { - $employee = new Employee(); - $employee->setAccount((int) ($request->getData('account') ?? 0)); + $account = new Account(); + $account->setName1((string) ($request->getData('name1') ?? '')); + $account->setName2((string) ($request->getData('name2') ?? '')); + $account->setName3((string) ($request->getData('name3') ?? '')); + $account->setName3((string) ($request->getData('email') ?? '')); + + $profile = new Profile($account); + $profile->setBirthday(new \DateTime((string) ($request->getData('birthday') ?? 'now'))); + + $employee = new Employee($profile); return $employee; } diff --git a/Models/Employee.php b/Models/Employee.php index 5d27135..93a222e 100644 --- a/Models/Employee.php +++ b/Models/Employee.php @@ -35,33 +35,199 @@ class Employee implements ArrayableInterface, \JsonSerializable */ private int $id = 0; - private $account = null; + /** + * Account profile. + * + * @var null|int|Profile + * @since 1.0.0 + */ + private $profile = null; - private $history = []; + /** + * Employee department/position history. + * + * @var array + * @since 1.0.0 + */ + private array $companyHistory = []; - public function setAccount($account) : void + /** + * Employee education history. + * + * @todo: implement! + * + * @var array + * @since 1.0.0 + */ + private array $educationHistory = []; + + /** + * Employee external work history. + * + * @var array + * @since 1.0.0 + */ + private array $workHistory = []; + + /** + * Employee hash used for time tracking / employee card + * + * @var string + * @since 1.0.0 + */ + private string $semiPrivateHash = ''; + + /** + * Employee hash length used for time tracking / employee card + * + * @var int + * @since 1.0.0 + */ + private const SEMI_PRIVATE_HASH_LENGTH = 64; + + /** + * Constructor. + * + * @param null|Profile $profile Account profile to initialize this employee with + * + * @since 1.0.0 + */ + public function __construct($profile = null) { - $this->account = $account; - } - - public function getAccount() - { - return $this->account; + $this->profile = $profile; + $this->semiPrivateHash = \random_bytes(self::SEMI_PRIVATE_HASH_LENGTH); } + /** + * Get account id. + * + * @return int Account id + * + * @since 1.0.0 + */ public function getId() : int { return $this->id; } - public function getHistory() : array + /** + * Get profile. + * + * @return null|int|Profile + * + * @since 1.0.0 + */ + public function getProfile() { - return $this->history; + return $this->profile; } + /** + * Update semi private hash. + * + * @return void + * + * @since 1.0.0 + */ + public function updateSemiPrivateHash() : void + { + $this->semiPrivateHash = \random_bytes(self::SEMI_PRIVATE_HASH_LENGTH); + } + + /** + * Get semi private hash. + * + * @return string + * + * @since 1.0.0 + */ + public function getSemiPrivateHash() : string + { + return $this->semiPrivateHash; + } + + /** + * Compare two hashs + * + * @return bool + * + * @since 1.0.0 + */ + public function compareSemiPrivateHash(string $hash) : bool + { + return \hash_equals($this->semiPrivateHash, $hash); + } + + /** + * Get employee company history. + * + * @return array Employee history + * + * @since 1.0.0 + */ + public function getHistory() : array + { + return $this->companyHistory; + } + + /** + * Get newest company history. + * + * @return EmployeeHistory + * + * @since 1.0.0 + */ public function getNewestHistory() : EmployeeHistory { - return empty($this->history) ? new NullEmployeeHistory : end($this->history); + return empty($this->companyHistory) ? new NullEmployeeHistory : end($this->companyHistory); + } + + /** + * Get employee company education history. + * + * @return array Employee education history + * + * @since 1.0.0 + */ + public function getEducationHistory() : array + { + return $this->educationHistory; + } + + /** + * Get newest company education history. + * + * @return EmployeeEducationHistory + * + * @since 1.0.0 + */ + public function getNewestEducationHistory() : EmployeeEducationHistory + { + return empty($this->educationHistory) ? new NullEmployeeEducationHistory : end($this->educationHistory); + } + + /** + * Get employee company work. + * + * @return array Employee work + * + * @since 1.0.0 + */ + public function getWorkHistory() : array + { + return $this->workHistory; + } + + /** + * Get newest company work. + * + * @return EmployeeWorkHistory + * + * @since 1.0.0 + */ + public function getNewestWorkHistory() : EmployeeWorkHistory + { + return empty($this->workHistory) ? new NullEmployeeWorkHistory : end($this->workHistory); } /** @@ -70,8 +236,8 @@ class Employee implements ArrayableInterface, \JsonSerializable public function toArray() : array { return [ - 'id' => $this->id, - 'account' => $this->account, + 'id' => $this->id, + 'profile' => $this->profile, ]; } diff --git a/Models/EmployeeActivityStatus.php b/Models/EmployeeActivityStatus.php new file mode 100644 index 0000000..ae01fab --- /dev/null +++ b/Models/EmployeeActivityStatus.php @@ -0,0 +1,31 @@ + ['name' => 'hr_staff_id', 'type' => 'int', 'internal' => 'id'], - 'hr_staff_account' => ['name' => 'hr_staff_account', 'type' => 'int', 'internal' => 'account'], + 'hr_staff_id' => ['name' => 'hr_staff_id', 'type' => 'int', 'internal' => 'id'], + 'hr_staff_account' => ['name' => 'hr_staff_account', 'type' => 'int', 'internal' => 'account'], + 'hr_staff_smiPHash' => ['name' => 'hr_staff_smiPHash', 'type' => 'int', 'internal' => 'semiPrivateHash'], ]; /** @@ -48,7 +49,7 @@ final class EmployeeMapper extends DataMapperAbstract */ protected static array $belongsTo = [ 'account' => [ - 'mapper' => AccountMapper::class, + 'mapper' => ProfileMapper::class, 'src' => 'hr_staff_account', ], ]; @@ -60,7 +61,7 @@ final class EmployeeMapper extends DataMapperAbstract * @since 1.0.0 */ protected static array $hasMany = [ - 'history' => [ + 'company' => [ 'mapper' => EmployeeHistoryMapper::class, 'table' => 'hr_staff_history', 'dst' => 'hr_staff_history_staff', diff --git a/Models/NullEmployee.php b/Models/NullEmployee.php index 2629274..e9e578a 100644 --- a/Models/NullEmployee.php +++ b/Models/NullEmployee.php @@ -4,7 +4,7 @@ * * PHP Version 7.4 * - * @package Modules\News + * @package Modules\News\Models * @copyright Dennis Eichhorn * @license OMS License 1.0 * @version 1.0.0 @@ -17,7 +17,7 @@ namespace Modules\HumanResourceManagement\Models; /** * Null model * - * @package Modules\HumanResourceManagement + * @package Modules\HumanResourceManagement\Models * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 diff --git a/Models/NullEmployeeHistory.php b/Models/NullEmployeeHistory.php index 01a06db..2a3aa32 100644 --- a/Models/NullEmployeeHistory.php +++ b/Models/NullEmployeeHistory.php @@ -4,7 +4,7 @@ * * PHP Version 7.4 * - * @package Modules\News + * @package Modules\News\Models * @copyright Dennis Eichhorn * @license OMS License 1.0 * @version 1.0.0 @@ -17,7 +17,7 @@ namespace Modules\HumanResourceManagement\Models; /** * Null model * - * @package Modules\HumanResourceManagement + * @package Modules\HumanResourceManagement\Models * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 diff --git a/Models/PermissionState.php b/Models/PermissionState.php index de399bd..a814db3 100644 --- a/Models/PermissionState.php +++ b/Models/PermissionState.php @@ -4,7 +4,7 @@ * * PHP Version 7.4 * - * @package Modules\HumanResourceManagement + * @package Modules\HumanResourceManagement\Models * @copyright Dennis Eichhorn * @license OMS License 1.0 * @version 1.0.0 @@ -19,7 +19,7 @@ use phpOMS\Stdlib\Base\Enum; /** * Permision state enum. * - * @package Modules\HumanResourceManagement + * @package Modules\HumanResourceManagement\Models * @license OMS License 1.0 * @link https://orange-management.org * @since 1.0.0 diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index 921ee11..9b7e43d 100644 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -11,17 +11,24 @@ * @link https://orange-management.org */ return ['HumanResourceManagement' => [ + 'Account' => 'Account', + 'Active' => 'Active', + 'End' => 'End', + 'Inactive' => 'Inactive', + 'CreateFromAccount' => 'Create from account', 'Birthday' => 'Birthday', 'Clocking' => 'Clocking', 'Department' => 'Department', 'Departments' => 'Departments', 'Email' => 'Email', + 'Employee' => 'Employee', 'Employees' => 'Employees', 'History' => 'History', 'Name' => 'Name', 'Parent' => 'Parent', 'Personnel' => 'Personnel', 'Position' => 'Position', + 'Start' => 'Start', 'Shifts' => 'Shifts', 'Staff' => 'Staff', 'Status' => 'Status', diff --git a/Theme/Backend/staff-create.tpl.php b/Theme/Backend/staff-create.tpl.php index 4551789..22ff608 100644 --- a/Theme/Backend/staff-create.tpl.php +++ b/Theme/Backend/staff-create.tpl.php @@ -10,6 +10,9 @@ * @version 1.0.0 * @link https://orange-management.org */ + +use \Modules\HumanResourceManagement\Models\EmployeeActivityStatus; + /** * @var \phpOMS\Views\View $this */ @@ -18,53 +21,63 @@ echo $this->getData('nav')->render(); ?>
-
+
-

getHtml('Account'); ?>

+

getHtml('Employee'); ?>

-
+ -
-
-
-
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-

getHtml('CreateFromExistingAccount'); ?>

+

getHtml('CreateFromAccount'); ?>

-
+ -
-
getData('accSelector')->render('iAccount', 'account', true); ?> +
+
getData('accSelector')->render('iAccount', 'accounts', true); ?> +