Latest updates from IceHrmPro
This commit is contained in:
@@ -29,32 +29,32 @@ class AttendanceAdminManager extends AbstractModuleManager
|
||||
|
||||
public function setupRestEndPoints()
|
||||
{
|
||||
\Classes\Macaw::get(REST_API_PATH.'attendance/(:num)', function ($pathParams) {
|
||||
\Classes\Macaw::get(REST_API_PATH.'attendance/(:num)', function ($pathParams = null) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('get', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::get(REST_API_PATH.'attendance', function ($pathParams) {
|
||||
\Classes\Macaw::get(REST_API_PATH.'attendance', function ($pathParams = null) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('listAll', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::get(REST_API_PATH.'employee/(:num)/attendance', function ($pathParams) {
|
||||
\Classes\Macaw::get(REST_API_PATH.'employee/(:num)/attendance', function ($pathParams = null) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('listEmployeeAttendance', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::post(REST_API_PATH.'attendance', function ($pathParams) {
|
||||
\Classes\Macaw::post(REST_API_PATH.'attendance', function ($pathParams = null) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('post', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::delete(REST_API_PATH.'attendance/(:num)', function ($pathParams) {
|
||||
\Classes\Macaw::delete(REST_API_PATH.'attendance/(:num)', function ($pathParams = null) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('delete', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::post(REST_API_PATH.'attendance/punch-in', function ($pathParams) {
|
||||
\Classes\Macaw::post(REST_API_PATH.'attendance/punch-in', function ($pathParams = null) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('punchIn', $pathParams);
|
||||
});
|
||||
@@ -64,7 +64,7 @@ class AttendanceAdminManager extends AbstractModuleManager
|
||||
$restEndPoint->process('getOpenPunch', [$employeeId, $date]);
|
||||
});
|
||||
|
||||
\Classes\Macaw::post(REST_API_PATH.'attendance/punch-out', function ($pathParams) {
|
||||
\Classes\Macaw::post(REST_API_PATH.'attendance/punch-out', function ($pathParams = null) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('punchOut', $pathParams);
|
||||
});
|
||||
@@ -85,10 +85,10 @@ class AttendanceAdminManager extends AbstractModuleManager
|
||||
public function initQuickAccessMenu()
|
||||
{
|
||||
UIManager::getInstance()->addQuickAccessMenuItem(
|
||||
"Clocked In Employees",
|
||||
"fa-clock-o",
|
||||
CLIENT_BASE_URL."?g=admin&n=attendance&m=admin_Employees#tabAttendanceStatus",
|
||||
array("Admin","Manager")
|
||||
'Clocked In Employees',
|
||||
'fa-clock-o',
|
||||
CLIENT_BASE_URL.'?g=admin&n=attendance&m=admin_Employees#tabAttendanceStatus',
|
||||
array('Admin','Manager')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Attendance\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class Attendance extends BaseModel
|
||||
@@ -33,4 +34,13 @@ class Attendance extends BaseModel
|
||||
{
|
||||
return array('element','save','delete');
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('attendance', 'admin'),
|
||||
new ModuleAccess('attendance', 'user'),
|
||||
new ModuleAccess('attendance_sheets', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Attendance\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Classes\SettingsManager;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Model\BaseModel;
|
||||
@@ -136,4 +137,12 @@ class AttendanceStatus extends BaseModel
|
||||
{
|
||||
return array("element","save","delete");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('attendance', 'admin'),
|
||||
new ModuleAccess('attendance', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,18 +97,16 @@ class AttendanceRestEndPoint extends RestEndPoint
|
||||
return new IceResponse(IceResponse::ERROR, self::RESPONSE_ERR_PERMISSION_DENIED, 403);
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
"employee" => ["Employee", "id", "first_name+last_name"],
|
||||
];
|
||||
$mapping = '{"employee": [ "Employee", "id", "first_name+last_name" ]}';
|
||||
|
||||
$emp = BaseService::getInstance()->getElement(
|
||||
self::ELEMENT_NAME,
|
||||
$parameter,
|
||||
json_encode($mapping),
|
||||
null,
|
||||
true
|
||||
);
|
||||
|
||||
$emp = $this->enrichElement($emp, $mapping);
|
||||
$emp = $this->enrichElement($emp, json_decode($mapping));
|
||||
if (!empty($emp)) {
|
||||
$emp = $this->cleanObject($emp);
|
||||
return new IceResponse(IceResponse::SUCCESS, $emp);
|
||||
|
||||
@@ -52,6 +52,8 @@ class BaseService
|
||||
public $modelClassMap = array();
|
||||
public $currentProfileId = false;
|
||||
|
||||
protected $cacheService = null;
|
||||
|
||||
protected $pro = null;
|
||||
|
||||
private static $me = null;
|
||||
@@ -109,14 +111,11 @@ class BaseService
|
||||
$filter = json_decode($filterStr, true);
|
||||
|
||||
if (!empty($filter)) {
|
||||
LogManager::getInstance()->debug("Building filter query");
|
||||
if (method_exists($obj, 'getCustomFilterQuery')) {
|
||||
LogManager::getInstance()->debug("Method: getCustomFilterQuery exists");
|
||||
$response = $obj->getCustomFilterQuery($filter);
|
||||
$query = $response[0];
|
||||
$queryData = $response[1];
|
||||
} else {
|
||||
LogManager::getInstance()->debug("Method: getCustomFilterQuery not found");
|
||||
$defaultFilterResp = $this->buildDefaultFilterQuery($filter);
|
||||
$query = $defaultFilterResp[0];
|
||||
$queryData = $defaultFilterResp[1];
|
||||
@@ -134,8 +133,6 @@ class BaseService
|
||||
$cemp = $this->getCurrentProfileId();
|
||||
if (!empty($cemp)) {
|
||||
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
|
||||
LogManager::getInstance()->debug("Query: ".$signInMappingField." = ?".$query.$orderBy);
|
||||
LogManager::getInstance()->debug("Query Data: ".print_r(array_merge(array($cemp), $queryData), true));
|
||||
$list = $obj->Find($signInMappingField." = ?".$query.$orderBy, array_merge(array($cemp), $queryData));
|
||||
} else {
|
||||
$list = array();
|
||||
@@ -194,14 +191,14 @@ class BaseService
|
||||
$query.=" and (";
|
||||
}
|
||||
|
||||
$query.=$k." like ?";
|
||||
$query.=$k." = ?";
|
||||
|
||||
if ($i < $length -1) {
|
||||
$query.=" or ";
|
||||
} else {
|
||||
$query.=")";
|
||||
}
|
||||
$queryData[] = "%".$v[$i]."%";
|
||||
$queryData[] = $v[$i];
|
||||
}
|
||||
} else {
|
||||
if (!empty($v) && $v != 'NULL') {
|
||||
@@ -231,6 +228,132 @@ class BaseService
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getDataCount()
|
||||
{
|
||||
//Get Total row count
|
||||
$totalRows = 0;
|
||||
|
||||
if (!isset($_REQUEST['objects'])) {
|
||||
$countFilterQuery = "";
|
||||
$countFilterQueryData = array();
|
||||
if (!empty($_REQUEST['ft'])) {
|
||||
$filter = json_decode($_REQUEST['ft']);
|
||||
if (!empty($filter)) {
|
||||
\Utils\LogManager::getInstance()->debug("Filter:" . print_r($filter, true));
|
||||
if (method_exists($obj, 'getCustomFilterQuery')) {
|
||||
$response = $obj->getCustomFilterQuery($filter);
|
||||
$countFilterQuery = $response[0];
|
||||
$countFilterQueryData = $response[1];
|
||||
} else {
|
||||
$defaultFilterResp = \Classes\BaseService::getInstance()->buildDefaultFilterQuery($filter);
|
||||
$countFilterQuery = $defaultFilterResp[0];
|
||||
$countFilterQueryData = $defaultFilterResp[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (in_array($table, \Classes\BaseService::getInstance()->userTables)
|
||||
&& !$skipProfileRestriction && !$isSubOrdinates) {
|
||||
$cemp = \Classes\BaseService::getInstance()->getCurrentProfileId();
|
||||
$sql = "Select count(id) as count from "
|
||||
. $obj->_table . " where " . SIGN_IN_ELEMENT_MAPPING_FIELD_NAME . " = ? " . $countFilterQuery;
|
||||
array_unshift($countFilterQueryData, $cemp);
|
||||
|
||||
$rowCount = $obj->DB()->Execute($sql, $countFilterQueryData);
|
||||
} else {
|
||||
if ($isSubOrdinates) {
|
||||
$cemp = \Classes\BaseService::getInstance()->getCurrentProfileId();
|
||||
$profileClass = \Classes\BaseService::getInstance()->getFullQualifiedModelClassName(
|
||||
ucfirst(SIGN_IN_ELEMENT_MAPPING_FIELD_NAME)
|
||||
);
|
||||
$subordinate = new $profileClass();
|
||||
$subordinates = $subordinate->Find("supervisor = ?", array($cemp));
|
||||
|
||||
$cempObj = new \Employees\Common\Model\Employee();
|
||||
$cempObj->Load("id = ?", array($cemp));
|
||||
|
||||
if ($obj->getUserOnlyMeAccessField() == 'id'
|
||||
&& \Classes\SettingsManager::getInstance()->getSetting(
|
||||
'System: Company Structure Managers Enabled'
|
||||
) == 1
|
||||
&& \Company\Common\Model\CompanyStructure::isHeadOfCompanyStructure($cempObj->department, $cemp)
|
||||
) {
|
||||
if (empty($subordinates)) {
|
||||
$subordinates = array();
|
||||
}
|
||||
|
||||
$childCompaniesIds = array();
|
||||
if (\Classes\SettingsManager::getInstance()->getSetting(
|
||||
'System: Child Company Structure Managers Enabled'
|
||||
) == '1'
|
||||
) {
|
||||
$childCompaniesResp = \Company\Common\Model\CompanyStructure::getAllChildCompanyStructures(
|
||||
$cempObj->department
|
||||
);
|
||||
$childCompanies = $childCompaniesResp->getObject();
|
||||
|
||||
foreach ($childCompanies as $cc) {
|
||||
$childCompaniesIds[] = $cc->id;
|
||||
}
|
||||
} else {
|
||||
$childCompaniesIds[] = $cempObj->department;
|
||||
}
|
||||
|
||||
if (!empty($childCompaniesIds)) {
|
||||
$childStructureSubordinates = $subordinate->Find(
|
||||
"department in (" . implode(',', $childCompaniesIds) . ") and id != ?",
|
||||
array($cemp)
|
||||
);
|
||||
$subordinates = array_merge($subordinates, $childStructureSubordinates);
|
||||
}
|
||||
}
|
||||
|
||||
$subordinatesIds = "";
|
||||
foreach ($subordinates as $sub) {
|
||||
if ($subordinatesIds != "") {
|
||||
$subordinatesIds .= ",";
|
||||
}
|
||||
$subordinatesIds .= $sub->id;
|
||||
}
|
||||
if ($obj->allowIndirectMapping()) {
|
||||
$indeirectEmployees = $subordinate->Find(
|
||||
"indirect_supervisors IS NOT NULL and indirect_supervisors <> '' and status = 'Active'",
|
||||
array()
|
||||
);
|
||||
foreach ($indeirectEmployees as $ie) {
|
||||
$indirectSupervisors = json_decode($ie->indirect_supervisors, true);
|
||||
if (in_array($cemp, $indirectSupervisors)) {
|
||||
if ($subordinatesIds != "") {
|
||||
$subordinatesIds .= ",";
|
||||
}
|
||||
$subordinatesIds .= $ie->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
$sql = "Select count(id) as count from " . $obj->_table .
|
||||
" where " . $obj->getUserOnlyMeAccessField() . " in (" . $subordinatesIds . ") "
|
||||
. $countFilterQuery;
|
||||
$rowCount = $obj->DB()->Execute($sql, $countFilterQueryData);
|
||||
} else {
|
||||
$sql = "Select count(id) as count from " . $obj->_table;
|
||||
if (!empty($countFilterQuery)) {
|
||||
$sql .= " where 1=1 " . $countFilterQuery;
|
||||
}
|
||||
$rowCount = $obj->DB()->Execute($sql, $countFilterQueryData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($rowCount) && !empty($rowCount)) {
|
||||
foreach ($rowCount as $cnt) {
|
||||
$totalRows = $cnt['count'];
|
||||
}
|
||||
}
|
||||
|
||||
return $totalRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* An extention of get method for the use of data tables with ability to search
|
||||
* @method getData
|
||||
@@ -545,7 +668,13 @@ class BaseService
|
||||
foreach ($map as $k => $v) {
|
||||
$fTable = $this->getFullQualifiedModelClassName($v[0]);
|
||||
$tObj = new $fTable();
|
||||
$tObj->Load($v[1]."= ?", array($item->$k));
|
||||
$tObj = $tObj->Find($v[1]."= ?", array($item->$k));
|
||||
|
||||
if (is_array($tObj)) {
|
||||
$tObj = $tObj[0];
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($tObj->{$v[1]} == $item->$k) {
|
||||
$v[2] = str_replace("+", " ", $v[2]);
|
||||
@@ -556,11 +685,11 @@ class BaseService
|
||||
$item->$k = $tObj->{$v[2]};
|
||||
} else {
|
||||
$objVal = "";
|
||||
foreach ($values as $v) {
|
||||
foreach ($values as $val2) {
|
||||
if ($objVal != "") {
|
||||
$objVal .= " ";
|
||||
}
|
||||
$objVal .= $tObj->$v;
|
||||
$objVal .= $tObj->$val2;
|
||||
}
|
||||
$idField = $k."_id";
|
||||
$item->$idField = $item->$k;
|
||||
@@ -629,12 +758,16 @@ class BaseService
|
||||
if (count($values) == 1) {
|
||||
return $targetObject->{$nameField};
|
||||
}
|
||||
$objVal = "";
|
||||
$objVal = '';
|
||||
foreach ($values as $value) {
|
||||
if ($objVal != "") {
|
||||
$objVal .= " ";
|
||||
}
|
||||
$objVal .= $targetObject->$value;
|
||||
if (substr($value, 0, 1) !== ':') {
|
||||
$objVal .= $targetObject->{$value};
|
||||
} else {
|
||||
$objVal .= substr($value, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return $objVal;
|
||||
@@ -646,7 +779,9 @@ class BaseService
|
||||
* @param $table {String} model class name of the table to add data (e.g for Users table model class name is User)
|
||||
* @param $obj {Array} an associative array with field names and values for the new object.
|
||||
* If the object id is not empty an existing object will be updated
|
||||
* @return {Object} newly added or updated element of type $table
|
||||
* @param null $postObject
|
||||
* @return IceResponse {Object} newly added or updated element of type $table newly added or updated
|
||||
* element of type $table
|
||||
*/
|
||||
|
||||
public function addElement($table, $obj, $postObject = null)
|
||||
@@ -757,7 +892,6 @@ class BaseService
|
||||
}
|
||||
|
||||
$customFields = $ele->getCustomFields($obj);
|
||||
LogManager::getInstance()->error("Custom:".json_encode($customFields));
|
||||
foreach ($obj as $k => $v) {
|
||||
if (isset($customFields[$k])) {
|
||||
$this->customFieldManager->addCustomField($table, $ele->id, $k, $v);
|
||||
@@ -898,7 +1032,7 @@ class BaseService
|
||||
$list = $ele->$method(array());
|
||||
}
|
||||
} else {
|
||||
LogManager::getInstance()->debug("Could not find method:".$method." in Class:".$table);
|
||||
LogManager::getInstance()->error("Could not find method:".$method." in Class:".$table);
|
||||
$list = $ele->Find('1 = 1', array());
|
||||
}
|
||||
} else {
|
||||
@@ -1106,10 +1240,12 @@ class BaseService
|
||||
|
||||
public function cleanUpUser($obj)
|
||||
{
|
||||
$obj = $this->cleanUpAdoDB($obj);
|
||||
$obj = $this->cleanUpAll($obj);
|
||||
unset($obj->password);
|
||||
unset($obj->login_hash);
|
||||
unset($obj->googleUserData);
|
||||
unset($obj->wrong_password_count);
|
||||
unset($obj->last_wrong_attempt_at);
|
||||
|
||||
return $obj;
|
||||
}
|
||||
@@ -1137,14 +1273,12 @@ class BaseService
|
||||
|
||||
public function checkSecureAccess($type, $object, $table, $request)
|
||||
{
|
||||
$accessMatrix = array();
|
||||
|
||||
//Construct permission method
|
||||
$permMethod = "get".$this->currentUser->user_level."Access";
|
||||
$permMethod = "get".str_replace(' ', '', $this->currentUser->user_level)."Access";
|
||||
$userOnlyMeAccessRequestField = $object->getUserOnlyMeAccessRequestField();
|
||||
$userOnlyMeAccessField = $object->getUserOnlyMeAccessField();
|
||||
if (method_exists($object, $permMethod)) {
|
||||
$accessMatrix = $object->$permMethod();
|
||||
$accessMatrix = $object->$permMethod($this->currentUser->user_roles);
|
||||
} else {
|
||||
$accessMatrix = $object->getDefaultAccessLevel();
|
||||
}
|
||||
@@ -1174,7 +1308,7 @@ class BaseService
|
||||
// Employees should be able to update their own records
|
||||
if (!empty($table) && in_array($type, $accessMatrix)) {
|
||||
if (!empty($this->currentUser->$userOnlyMeAccessRequestField)
|
||||
&& in_array($table, $this->userTables) ) {
|
||||
&& in_array($table, $this->userTables)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1183,7 +1317,15 @@ class BaseService
|
||||
$ret['status'] = "ERROR";
|
||||
$ret['message'] = $type." ".get_class($object)." Access violation";
|
||||
echo json_encode($ret);
|
||||
exit();
|
||||
$exception = new \Exception(
|
||||
sprintf(
|
||||
'%s : %s',
|
||||
'Access violation',
|
||||
json_encode([$type, $table, get_class($object), $request, json_encode($this->currentUser)])
|
||||
)
|
||||
);
|
||||
LogManager::getInstance()->notifyException($exception);
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
public function getInstanceId()
|
||||
@@ -1740,13 +1882,19 @@ END;
|
||||
if ($obj->$name != '') {
|
||||
$obj->$name .= ', ';
|
||||
}
|
||||
$tObj->Load($v[1] . "= ?", array($partialId));
|
||||
$obj->$name .= $this->getCombinedValue($v[2], $tObj);
|
||||
$tObjArr = $tObj->Find($v[1] . "= ?", [$partialId]);
|
||||
if (!is_array($tObjArr) || empty($tObjArr[0])) {
|
||||
continue;
|
||||
}
|
||||
$obj->$name .= $this->getCombinedValue($v[2], $tObjArr[0]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$tObj->Load($v[1] . "= ?", array($obj->$k));
|
||||
$obj->$name = $this->getCombinedValue($v[2], $tObj);
|
||||
$tObjArr = $tObj->Find($v[1] . "= ?", [$obj->$k]);
|
||||
if (!is_array($tObjArr) || empty($tObjArr[0])) {
|
||||
continue;
|
||||
}
|
||||
$obj->$name = $this->getCombinedValue($v[2], $tObjArr[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1767,4 +1915,25 @@ END;
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RedisCacheService
|
||||
*/
|
||||
public function getCacheService()
|
||||
{
|
||||
return $this->cacheService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CacheService $redisCacheService
|
||||
*/
|
||||
public function setCacheService($redisCacheService)
|
||||
{
|
||||
$this->cacheService = $redisCacheService;
|
||||
}
|
||||
|
||||
public function queryCacheEnabled()
|
||||
{
|
||||
return defined('QUERY_CACHE') && QUERY_CACHE === true;
|
||||
}
|
||||
}
|
||||
|
||||
12
core/src/Classes/CacheService.php
Normal file
12
core/src/Classes/CacheService.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
interface CacheService
|
||||
{
|
||||
public function setDBQuery($entity, $query, $params, $result, $ttl = 600);
|
||||
|
||||
public function getDBQuery($entity, $query, $params);
|
||||
|
||||
public function deleteByEntity($entity);
|
||||
}
|
||||
@@ -42,7 +42,7 @@ class IceCron
|
||||
$time = intval($this->cron->time);
|
||||
|
||||
if (empty($frequency) || !is_int($frequency)) {
|
||||
LogManager::getInstance()->debug(
|
||||
LogManager::getInstance()->error(
|
||||
"Cron ".$this->cron->name." is not running since frequency is not an integer"
|
||||
);
|
||||
return false;
|
||||
|
||||
@@ -26,6 +26,7 @@ class EmailSenderTask implements IceTask
|
||||
$emailSender->sendEmailFromDB($email);
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->error("Error sending email:".$e->getMessage());
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
}
|
||||
|
||||
$email->status = 'Sent';
|
||||
|
||||
64
core/src/Classes/Cron/Task/NewCandidateEmailTask.php
Normal file
64
core/src/Classes/Cron/Task/NewCandidateEmailTask.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Classes\Cron\Task;
|
||||
|
||||
use Candidates\Admin\Api\CandidatesActionManager;
|
||||
use Candidates\Common\Email\CandidatesEmailSender;
|
||||
use Candidates\Common\Model\Candidate;
|
||||
use Classes\BaseService;
|
||||
use Classes\Cron\IceTask;
|
||||
use Employees\Common\Model\Employee;
|
||||
use JobPositions\Common\Model\Job;
|
||||
use Users\Common\Model\User;
|
||||
|
||||
class NewCandidateEmailTask implements IceTask
|
||||
{
|
||||
|
||||
public function execute($cron)
|
||||
{
|
||||
$candidate = new Candidate();
|
||||
$candidates = $candidate->Find('source = ? and emailSent = ?', [Candidate::SOURCE_APPLIED, 0]);
|
||||
foreach ($candidates as $candidate) {
|
||||
$job = new Job();
|
||||
$job->Load('id = ?', [$candidate->jobId]);
|
||||
|
||||
$candidateActionManager = new CandidatesActionManager();
|
||||
$candidateActionManager->setBaseService(BaseService::getInstance());
|
||||
$candidateEmailSender = new CandidatesEmailSender(
|
||||
BaseService::getInstance()->getEmailSender(),
|
||||
$candidateActionManager
|
||||
);
|
||||
|
||||
$candidate->emailSent = 1;
|
||||
$ok = $candidate->Save();
|
||||
|
||||
if (!$ok) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$candidateEmailSender->sendNewCandidateUserEmail($job->title, $candidate);
|
||||
|
||||
if (empty($job->hiringManager)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$manager = new Employee();
|
||||
$manager->Load('id = ?', [$job->hiringManager]);
|
||||
|
||||
$managerUser = new User();
|
||||
$managerUser->Load('employee = ?', [$manager->id]);
|
||||
|
||||
if (empty($managerUser->email)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$candidateEmailSender->sendNewCandidateManagerEmail(
|
||||
$job->title,
|
||||
$candidate,
|
||||
$manager->first_name,
|
||||
$managerUser->email
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
108
core/src/Classes/Cron/Task/RecruitmentEmailTask.php
Normal file
108
core/src/Classes/Cron/Task/RecruitmentEmailTask.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Classes\Cron\Task;
|
||||
|
||||
use Candidates\Admin\Api\CandidatesActionManager;
|
||||
use Candidates\Common\Email\CandidatesEmailSender;
|
||||
use Candidates\Common\Model\Candidate;
|
||||
use Candidates\Common\Model\Interview;
|
||||
use Classes\BaseService;
|
||||
use Classes\Cron\IceTask;
|
||||
use Employees\Common\Model\Employee;
|
||||
use JobPositions\Common\Model\Job;
|
||||
use Users\Common\Model\User;
|
||||
use Utils\LogManager;
|
||||
|
||||
class RecruitmentEmailTask implements IceTask
|
||||
{
|
||||
public function execute($cron)
|
||||
{
|
||||
$interview = new Interview();
|
||||
$interviews = $interview->Find('scheduleUpdated = ?', [1]);
|
||||
foreach ($interviews as $interview) {
|
||||
$job = new Job();
|
||||
$job->Load('id = ?', [$interview->job]);
|
||||
|
||||
$candidate = new Candidate();
|
||||
$candidate->Load('id = ?', [$interview->candidate]);
|
||||
|
||||
$manager = new Employee();
|
||||
$manager->Load('id = ?', [$job->hiringManager]);
|
||||
|
||||
$managerUser = new User();
|
||||
$managerUser->Load('employee = ?', [$manager->id]);
|
||||
|
||||
$candidateActionManager = new CandidatesActionManager();
|
||||
$candidateActionManager->setBaseService(BaseService::getInstance());
|
||||
$candidateEmailSender = new CandidatesEmailSender(
|
||||
BaseService::getInstance()->getEmailSender(),
|
||||
$candidateActionManager
|
||||
);
|
||||
|
||||
$interview->scheduleUpdated = 0;
|
||||
$ok = $interview->Save();
|
||||
|
||||
if (!$ok) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($job->hiringManager)) {
|
||||
$manager = new Employee();
|
||||
$manager->Load('id = ?', [$job->hiringManager]);
|
||||
|
||||
$managerUser = new User();
|
||||
$managerUser->Load('employee = ?', [$manager->id]);
|
||||
|
||||
if (empty($managerUser->email)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$candidateEmailSender->interviewScheduledManagerEmail(
|
||||
$job->title,
|
||||
$candidate,
|
||||
$manager->first_name,
|
||||
$managerUser->email,
|
||||
$interview
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($interview->interviewers)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$interviewerIds = null;
|
||||
try {
|
||||
$interviewerIds = json_decode($interview->interviewers, true);
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
}
|
||||
|
||||
if (empty($interviewerIds) && !is_array($interviewerIds)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($interviewerIds as $interviewerId) {
|
||||
$interviewer = new Employee();
|
||||
$interviewer->Load('id = ?', [$interviewerId]);
|
||||
|
||||
$interviewerUser = new User();
|
||||
$interviewerUser->Load('employee = ?', [$interviewer->id]);
|
||||
|
||||
if (empty($interviewerUser->email)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$candidateEmailSender->interviewScheduledInterviewerEmail(
|
||||
$job->title,
|
||||
$candidate,
|
||||
$manager->first_name,
|
||||
$managerUser->email,
|
||||
$interviewerUser->email,
|
||||
$interview,
|
||||
$interviewer
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,7 @@ class Aes
|
||||
$Nr = count($w)/$Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
|
||||
|
||||
$state = array(); // initialise 4xNb byte-array 'state' with input [<5B>3.4]
|
||||
for ($i = 0; $i<4*$Nb;
|
||||
$i++) {
|
||||
for ($i = 0; $i<4*$Nb; $i++) {
|
||||
$state[$i%4][floor($i/4)] = $input[$i];
|
||||
}
|
||||
|
||||
@@ -42,8 +41,7 @@ class Aes
|
||||
$state = self::addRoundKey($state, $w, $Nr, $Nb);
|
||||
|
||||
$output = array(4*$Nb); // convert state to 1-d array before returning [<5B>3.4]
|
||||
for ($i = 0; $i<4*$Nb;
|
||||
$i++) {
|
||||
for ($i = 0; $i<4*$Nb; $i++) {
|
||||
$output[$i] = $state[$i%4][floor($i/4)];
|
||||
}
|
||||
return $output;
|
||||
@@ -53,8 +51,7 @@ class Aes
|
||||
{
|
||||
// xor Round Key into state S [<5B>5.1.4]
|
||||
for ($r = 0; $r<4; $r++) {
|
||||
for ($c = 0; $c<$Nb;
|
||||
$c++) {
|
||||
for ($c = 0; $c<$Nb; $c++) {
|
||||
$state[$r][$c] ^= $w[$rnd*4+$c][$r];
|
||||
}
|
||||
}
|
||||
@@ -65,8 +62,7 @@ class Aes
|
||||
{
|
||||
// apply SBox to state S [<5B>5.1.1]
|
||||
for ($r = 0; $r<4; $r++) {
|
||||
for ($c = 0; $c<$Nb;
|
||||
$c++) {
|
||||
for ($c = 0; $c<$Nb; $c++) {
|
||||
$s[$r][$c] = self::$sBox[$s[$r][$c]];
|
||||
}
|
||||
}
|
||||
@@ -78,12 +74,10 @@ class Aes
|
||||
// shift row r of state S left by r bytes [<5B>5.1.2]
|
||||
$t = array(4);
|
||||
for ($r = 1; $r<4; $r++) {
|
||||
for ($c = 0; $c<4;
|
||||
$c++) {
|
||||
for ($c = 0; $c<4; $c++) {
|
||||
$t[$c] = $s[$r][($c+$r)%$Nb]; // shift into temp copy
|
||||
}
|
||||
for ($c = 0; $c<4;
|
||||
$c++) {
|
||||
for ($c = 0; $c<4; $c++) {
|
||||
$s[$r][$c] = $t[$c]; // and copy back
|
||||
}
|
||||
} // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
|
||||
@@ -133,21 +127,18 @@ class Aes
|
||||
|
||||
for ($i = $Nk; $i<($Nb*($Nr+1)); $i++) {
|
||||
$w[$i] = array();
|
||||
for ($t = 0; $t<4;
|
||||
$t++) {
|
||||
for ($t = 0; $t<4; $t++) {
|
||||
$temp[$t] = $w[$i-1][$t];
|
||||
}
|
||||
if ($i % $Nk == 0) {
|
||||
$temp = self::subWord(self::rotWord($temp));
|
||||
for ($t = 0; $t<4;
|
||||
$t++) {
|
||||
for ($t = 0; $t<4; $t++) {
|
||||
$temp[$t] ^= self::$rCon[$i/$Nk][$t];
|
||||
}
|
||||
} elseif ($Nk > 6 && $i%$Nk == 4) {
|
||||
$temp = self::subWord($temp);
|
||||
}
|
||||
for ($t = 0; $t<4;
|
||||
$t++) {
|
||||
for ($t = 0; $t<4; $t++) {
|
||||
$w[$i][$t] = $w[$i-$Nk][$t] ^ $temp[$t];
|
||||
}
|
||||
}
|
||||
@@ -157,8 +148,7 @@ class Aes
|
||||
private static function subWord($w)
|
||||
{
|
||||
// apply SBox to 4-byte word w
|
||||
for ($i = 0; $i<4;
|
||||
$i++) {
|
||||
for ($i = 0; $i<4; $i++) {
|
||||
$w[$i] = self::$sBox[$w[$i]];
|
||||
}
|
||||
return $w;
|
||||
@@ -168,8 +158,7 @@ class Aes
|
||||
{
|
||||
// rotate 4-byte word w left by one byte
|
||||
$tmp = $w[0];
|
||||
for ($i = 0; $i<3;
|
||||
$i++) {
|
||||
for ($i = 0; $i<3; $i++) {
|
||||
$w[$i] = $w[$i+1];
|
||||
}
|
||||
$w[3] = $tmp;
|
||||
|
||||
@@ -32,8 +32,7 @@ class AesCtr extends Aes
|
||||
// key expansion) - gives us well encrypted key
|
||||
$nBytes = $nBits/8; // no bytes in key
|
||||
$pwBytes = array();
|
||||
for ($i = 0; $i<$nBytes;
|
||||
$i++) {
|
||||
for ($i = 0; $i<$nBytes; $i++) {
|
||||
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
|
||||
}
|
||||
$key = Aes::cipher($pwBytes, Aes::keyExpansion($pwBytes));
|
||||
@@ -47,23 +46,19 @@ class AesCtr extends Aes
|
||||
$nonceSec = floor($nonce/1000);
|
||||
$nonceRnd = floor(rand(0, 0xffff));
|
||||
|
||||
for ($i = 0; $i<2;
|
||||
$i++) {
|
||||
for ($i = 0; $i<2; $i++) {
|
||||
$counterBlock[$i] = self::urs($nonceMs, $i*8) & 0xff;
|
||||
}
|
||||
for ($i = 0; $i<2;
|
||||
$i++) {
|
||||
for ($i = 0; $i<2; $i++) {
|
||||
$counterBlock[$i+2] = self::urs($nonceRnd, $i*8) & 0xff;
|
||||
}
|
||||
for ($i = 0; $i<4;
|
||||
$i++) {
|
||||
for ($i = 0; $i<4; $i++) {
|
||||
$counterBlock[$i+4] = self::urs($nonceSec, $i*8) & 0xff;
|
||||
}
|
||||
|
||||
// and convert it to a string to go on the front of the ciphertext
|
||||
$ctrTxt = '';
|
||||
for ($i = 0; $i<8;
|
||||
$i++) {
|
||||
for ($i = 0; $i<8; $i++) {
|
||||
$ctrTxt .= chr($counterBlock[$i]);
|
||||
}
|
||||
|
||||
@@ -77,12 +72,10 @@ class AesCtr extends Aes
|
||||
for ($b = 0; $b<$blockCount; $b++) {
|
||||
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
|
||||
// done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
|
||||
for ($c = 0; $c<4;
|
||||
$c++) {
|
||||
for ($c = 0; $c<4; $c++) {
|
||||
$counterBlock[15-$c] = self::urs($b, $c*8) & 0xff;
|
||||
}
|
||||
for ($c = 0; $c<4;
|
||||
$c++) {
|
||||
for ($c = 0; $c<4; $c++) {
|
||||
$counterBlock[15-$c-4] = self::urs($b/0x100000000, $c*8);
|
||||
}
|
||||
|
||||
@@ -124,8 +117,7 @@ class AesCtr extends Aes
|
||||
// use AES to encrypt password (mirroring encrypt routine)
|
||||
$nBytes = $nBits/8; // no bytes in key
|
||||
$pwBytes = array();
|
||||
for ($i = 0; $i<$nBytes;
|
||||
$i++) {
|
||||
for ($i = 0; $i<$nBytes; $i++) {
|
||||
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
|
||||
}
|
||||
$key = Aes::cipher($pwBytes, Aes::keyExpansion($pwBytes));
|
||||
@@ -134,8 +126,7 @@ class AesCtr extends Aes
|
||||
// recover nonce from 1st element of ciphertext
|
||||
$counterBlock = array();
|
||||
$ctrTxt = substr($ciphertext, 0, 8);
|
||||
for ($i = 0; $i<8;
|
||||
$i++) {
|
||||
for ($i = 0; $i<8; $i++) {
|
||||
$counterBlock[$i] = ord(substr($ctrTxt, $i, 1));
|
||||
}
|
||||
|
||||
@@ -145,8 +136,7 @@ class AesCtr extends Aes
|
||||
// separate ciphertext into blocks (skipping past initial 8 bytes)
|
||||
$nBlocks = ceil((strlen($ciphertext)-8) / $blockSize);
|
||||
$ct = array();
|
||||
for ($b = 0; $b<$nBlocks;
|
||||
$b++) {
|
||||
for ($b = 0; $b<$nBlocks; $b++) {
|
||||
$ct[$b] = substr($ciphertext, 8+$b*$blockSize, 16);
|
||||
}
|
||||
$ciphertext = $ct; // ciphertext is now array of block-length strings
|
||||
@@ -156,12 +146,10 @@ class AesCtr extends Aes
|
||||
|
||||
for ($b = 0; $b<$nBlocks; $b++) {
|
||||
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
|
||||
for ($c = 0; $c<4;
|
||||
$c++) {
|
||||
for ($c = 0; $c<4; $c++) {
|
||||
$counterBlock[15-$c] = self::urs($b, $c*8) & 0xff;
|
||||
}
|
||||
for ($c = 0; $c<4;
|
||||
$c++) {
|
||||
for ($c = 0; $c<4; $c++) {
|
||||
$counterBlock[15-$c-4] = self::urs(($b+1)/0x100000000-1, $c*8) & 0xff;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ class DataReader
|
||||
$sortData = $query->getSortingData();
|
||||
$data = \Classes\BaseService::getInstance()->getData(
|
||||
$table,
|
||||
$query->getFieldMapping(),
|
||||
json_encode($query->getFilters()),
|
||||
null,
|
||||
$query->getFilters(),
|
||||
$query->getOrderBy(),
|
||||
$sLimit,
|
||||
json_encode($query->getColumns()),
|
||||
|
||||
@@ -59,7 +59,7 @@ class DataQuery
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldMapping()
|
||||
{
|
||||
@@ -197,7 +197,7 @@ class DataQuery
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $fieldMapping
|
||||
* @param string $fieldMapping
|
||||
*/
|
||||
public function setFieldMapping($fieldMapping)
|
||||
{
|
||||
@@ -205,9 +205,9 @@ class DataQuery
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $filters
|
||||
* @param $filters
|
||||
*/
|
||||
public function setFilters(array $filters)
|
||||
public function setFilters($filters)
|
||||
{
|
||||
$this->filters = $filters;
|
||||
}
|
||||
@@ -229,9 +229,9 @@ class DataQuery
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $sortColumn
|
||||
* @param string $sortColumn
|
||||
*/
|
||||
public function setSortColumn(bool $sortColumn)
|
||||
public function setSortColumn($sortColumn)
|
||||
{
|
||||
$this->sortColumn = $sortColumn;
|
||||
}
|
||||
|
||||
97
core/src/Classes/DomainAwareInputCleaner.php
Normal file
97
core/src/Classes/DomainAwareInputCleaner.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Classes;
|
||||
|
||||
|
||||
class DomainAwareInputCleaner
|
||||
{
|
||||
public function cleanTableColumn($input)
|
||||
{
|
||||
if ($this->isEmpty($input) || $this->isValidColumnName($input)) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function cleanMapping($mapping)
|
||||
{
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
public function cleanOrderBy($orderBy)
|
||||
{
|
||||
if (empty($orderBy)) {
|
||||
return $orderBy;
|
||||
}
|
||||
|
||||
$suffix = '';
|
||||
if (strstr($orderBy, ' desc')) {
|
||||
$suffix = ' desc';
|
||||
$orderBy = str_replace(' desc', '', $orderBy);
|
||||
}
|
||||
|
||||
if (!$this->cleanTableColumn($orderBy)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $orderBy.$suffix;
|
||||
}
|
||||
|
||||
public function cleanColumns($columns)
|
||||
{
|
||||
if (empty($columns)) {
|
||||
return $columns;
|
||||
}
|
||||
|
||||
$columnData = json_decode($columns, true);
|
||||
|
||||
foreach ($columnData as $column) {
|
||||
if (!$this->isValidColumnName($column)) {
|
||||
return '[]';
|
||||
}
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
public function cleanFilters($filters)
|
||||
{
|
||||
if (empty($filters)) {
|
||||
return $filters;
|
||||
}
|
||||
|
||||
$filterData = json_decode($filters, true);
|
||||
foreach ($filterData as $name => $value) {
|
||||
if (!$this->isValidColumnName($name) || !$this->isValidFilterValue($value)) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
return $filters;
|
||||
}
|
||||
|
||||
public function cleanSearch($searchTerm) {
|
||||
if (!$this->isValidFilterValue($searchTerm)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $searchTerm;
|
||||
}
|
||||
|
||||
private function isEmpty($input)
|
||||
{
|
||||
return empty($input) || trim($input) === '';
|
||||
}
|
||||
|
||||
private function isValidColumnName($input)
|
||||
{
|
||||
return !!preg_match('/^[a-zA-Z_]+$/', $input);
|
||||
}
|
||||
|
||||
private function isValidFilterValue($input)
|
||||
{
|
||||
return !!preg_match('/^[-_: \p{L}]+$/u', $input);
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,10 @@
|
||||
|
||||
namespace Classes\Email;
|
||||
|
||||
use Classes\Crypt\AesCtr;
|
||||
use Classes\PasswordManager;
|
||||
use Classes\UIManager;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Model\EmailLogEntry;
|
||||
use Model\IceEmail;
|
||||
use Users\Common\Model\User;
|
||||
use Utils\LogManager;
|
||||
@@ -145,7 +146,16 @@ abstract class EmailSender
|
||||
$emailBody = str_replace("#_".$k."_#", $v, $emailBody);
|
||||
}
|
||||
|
||||
return $this->sendMail($subject, $emailBody, $toEmail, $fromEmail, $user->email, $ccList, $bccList, APP_NAME);
|
||||
return $this->sendEmailWithLogging(
|
||||
$subject,
|
||||
$emailBody,
|
||||
$toEmail,
|
||||
$fromEmail,
|
||||
$user->email,
|
||||
$ccList,
|
||||
$bccList,
|
||||
APP_NAME
|
||||
);
|
||||
}
|
||||
|
||||
public function sendEmailWithoutWrap($subject, $toEmail, $template, $params, $ccList = array(), $bccList = array())
|
||||
@@ -181,7 +191,47 @@ abstract class EmailSender
|
||||
$emailBody = str_replace("#_".$k."_#", $v, $emailBody);
|
||||
}
|
||||
|
||||
$this->sendMail($subject, $emailBody, $toEmail, $fromEmail, $user->email, $ccList, $bccList);
|
||||
$this->sendEmailWithLogging($subject, $emailBody, $toEmail, $fromEmail, $user->email, $ccList, $bccList);
|
||||
}
|
||||
|
||||
protected function sendEmailWithLogging(
|
||||
$subject,
|
||||
$body,
|
||||
$toEmail,
|
||||
$fromEmail,
|
||||
$replyToEmail = null,
|
||||
$ccList = array(),
|
||||
$bccList = array(),
|
||||
$fromName = null
|
||||
) {
|
||||
$emailLogEntry = new EmailLogEntry();
|
||||
$emailLogEntry->subject = $subject;
|
||||
$emailLogEntry->toEmail = $toEmail;
|
||||
$emailLogEntry->body = $body;
|
||||
$emailLogEntry->cclist = implode(',', $ccList);
|
||||
$emailLogEntry->bcclist = implode(',', $bccList);
|
||||
$emailLogEntry->created = date('Y-m-d H:i:s');
|
||||
$emailLogEntry->updated = date('Y-m-d H:i:s');
|
||||
|
||||
$result = $this->sendMail(
|
||||
$subject,
|
||||
$body,
|
||||
$toEmail,
|
||||
$fromEmail,
|
||||
$replyToEmail,
|
||||
$ccList,
|
||||
$bccList,
|
||||
$fromName
|
||||
);
|
||||
|
||||
$emailLogEntry->status = $result ? 'Sent' : 'Failed';
|
||||
$ok = $emailLogEntry->Save();
|
||||
|
||||
if (!$ok) {
|
||||
LogManager::getInstance()->error('Error adding email log for '.json_encode([$toEmail, $subject, $body]));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
abstract protected function sendMail(
|
||||
@@ -211,15 +261,8 @@ abstract class EmailSender
|
||||
//$params['user'] = $user->first_name." ".$user->last_name;
|
||||
$params['url'] = CLIENT_BASE_URL;
|
||||
|
||||
$newPassHash = array();
|
||||
$newPassHash["CLIENT_NAME"] = CLIENT_NAME;
|
||||
$newPassHash["oldpass"] = $user->password;
|
||||
$newPassHash["email"] = $user->email;
|
||||
$newPassHash["time"] = time();
|
||||
$json = json_encode($newPassHash);
|
||||
$encJson = PasswordManager::createPasswordRestKey($user);
|
||||
|
||||
$encJson = AesCtr::encrypt($json, $user->password, 256);
|
||||
$encJson = urlencode($user->id."-".$encJson);
|
||||
$params['passurl'] = CLIENT_BASE_URL."service.php?a=rsp&key=".$encJson;
|
||||
|
||||
$emailBody = file_get_contents(APP_BASE_PATH.'/templates/email/passwordReset.html');
|
||||
|
||||
@@ -51,10 +51,11 @@ class PHPMailer extends EmailSender
|
||||
}
|
||||
$headers .= 'ReplyTo: ' . $replyToEmail . "\r\n";
|
||||
$headers .= 'Ice-Mailer: PHP/' . phpversion();
|
||||
|
||||
|
||||
return mail($toEmail, $subject, $body, $headers);
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->error("Error sending email:" . $e->getMessage());
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ class SMTPEmailSender extends EmailSender
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->error("Error sending email:" . $e->getMessage());
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ class SNSEmailSender extends EmailSender
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->error("Error sending email:" . $e->getMessage());
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ class SwiftMailer extends EmailSender
|
||||
return $mailer->send($mail);
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->error("Error sending email:" . $e->getMessage());
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ class FileService
|
||||
|
||||
return null;
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -51,6 +52,7 @@ class FileService
|
||||
}
|
||||
$this->memcache->set($key, $data, $expire);
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +146,7 @@ class FileService
|
||||
$profile->image = $expireUrl;
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->error("Error generating profile image: ".$e->getMessage());
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
if ($profile->gender == 'Female') {
|
||||
$profile->image = BASE_URL."images/user_female.png";
|
||||
} else {
|
||||
|
||||
@@ -49,7 +49,7 @@ class LDAPManager
|
||||
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
|
||||
|
||||
// verify user and password
|
||||
$bind = @ldap_bind($ldap, $managerDN, $managerPassword);
|
||||
$bind = ldap_bind($ldap, $managerDN, $managerPassword);
|
||||
|
||||
LogManager::getInstance()->debug("LDAP Manager Bind:".print_r($bind, true));
|
||||
|
||||
@@ -60,6 +60,7 @@ class LDAPManager
|
||||
$result = ldap_search($ldap, $ldap_dn, $filter);
|
||||
LogManager::getInstance()->debug("LDAP Search Result:".print_r($result, true));
|
||||
if (!$result) {
|
||||
LogManager::getInstance()->error("Unable to search LDAP server");
|
||||
exit("Unable to search LDAP server");
|
||||
}
|
||||
$entries = ldap_get_entries($ldap, $result);
|
||||
|
||||
@@ -52,7 +52,6 @@ class LanguageManager
|
||||
$user = BaseService::getInstance()->getCurrentUser();
|
||||
if (empty($user) || empty($user->lang) || $user->lang == "NULL") {
|
||||
$lang = SettingsManager::getInstance()->getSetting('System: Language');
|
||||
LogManager::getInstance()->info("System Lang:".$lang);
|
||||
} else {
|
||||
$supportedLang = new SupportedLanguage();
|
||||
$supportedLang->Load("id = ?", array($user->lang));
|
||||
|
||||
@@ -41,6 +41,8 @@ class Macaw
|
||||
array_push(self::$routes, $uri);
|
||||
array_push(self::$methods, strtoupper($method));
|
||||
array_push(self::$callbacks, $callback);
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
57
core/src/Classes/MemoryCacheService.php
Normal file
57
core/src/Classes/MemoryCacheService.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
class MemoryCacheService implements CacheService
|
||||
{
|
||||
protected $appName = null;
|
||||
|
||||
protected $store = [];
|
||||
|
||||
public function __construct($appName)
|
||||
{
|
||||
$this->appName = $appName;
|
||||
}
|
||||
|
||||
protected function getAppKey($keyData)
|
||||
{
|
||||
return sprintf('%s-%s', $this->appName, implode('-', $keyData));
|
||||
}
|
||||
|
||||
|
||||
public function setDBQuery($entity, $query, $params, $result, $ttl = 600)
|
||||
{
|
||||
$this->store[$this->getAppKey($entity, $query, implode('-', $params))] = serialize($result);
|
||||
}
|
||||
|
||||
public function getDBQuery($entity, $query, $params)
|
||||
{
|
||||
|
||||
$data = $this->store[$this->getAppKey([$entity, $query, implode('-', $params)])];
|
||||
if (empty($data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = unserialize($data);
|
||||
if (empty($data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function deleteByEntity($entity)
|
||||
{
|
||||
$this->deleteByPrefix($entity.'-');
|
||||
$newStore = [];
|
||||
foreach ($this->store as $key => $val) {
|
||||
if (substr($key, 0, strlen($entity.'-')) === $entity.'-') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newStore[$key] = $val;
|
||||
}
|
||||
|
||||
$this->store = $newStore;
|
||||
}
|
||||
}
|
||||
36
core/src/Classes/ModuleAccess.php
Normal file
36
core/src/Classes/ModuleAccess.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
class ModuleAccess
|
||||
{
|
||||
protected $name;
|
||||
protected $group;
|
||||
|
||||
/**
|
||||
* ModuleAccess constructor.
|
||||
* @param $name
|
||||
* @param $group
|
||||
*/
|
||||
public function __construct($name, $group)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->group = $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getGroup()
|
||||
{
|
||||
return $this->group;
|
||||
}
|
||||
}
|
||||
70
core/src/Classes/ModuleAccessService.php
Normal file
70
core/src/Classes/ModuleAccessService.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
use Modules\Common\Model\Module;
|
||||
|
||||
class ModuleAccessService
|
||||
{
|
||||
protected $moduleMap = [];
|
||||
protected $moduleIdMap = [];
|
||||
|
||||
private static $me = null;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function getInstance()
|
||||
{
|
||||
if (empty(self::$me)) {
|
||||
self::$me = new ModuleAccessService();
|
||||
}
|
||||
|
||||
return self::$me;
|
||||
}
|
||||
|
||||
public function setModule($name, $group, $module)
|
||||
{
|
||||
$this->moduleMap[$group.'-'.$name] = $module;
|
||||
$this->moduleIdMap[$module->id] = $module;
|
||||
}
|
||||
|
||||
public function getModule($name, $group)
|
||||
{
|
||||
return $this->moduleMap[$group.'-'.$name];
|
||||
}
|
||||
|
||||
public function getModules()
|
||||
{
|
||||
return array_values($this->moduleMap);
|
||||
}
|
||||
|
||||
public function isModuleEnabledForUser($moduleId, $user)
|
||||
{
|
||||
$module = $this->moduleIdMap[$moduleId];
|
||||
$moduleUserLevels = json_decode($module->user_levels, true);
|
||||
$moduleUserRoles = json_decode($module->user_roles, true);
|
||||
$userRoles = json_decode($user->user_roles, true);
|
||||
|
||||
if (empty($moduleUserLevels)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (in_array($user->user_level, PermissionManager::RESTRICTED_USER_LEVELS)) {
|
||||
if (empty($userRoles)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$baseUserLevel = str_replace('Restricted ', '', $user->user_level);
|
||||
// In this case base user level should have access to the module
|
||||
if (!in_array($baseUserLevel, $moduleUserLevels)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return count(array_intersect($userRoles, $moduleUserRoles)) > 0;
|
||||
}
|
||||
|
||||
return in_array($user->user_level, $moduleUserLevels);
|
||||
}
|
||||
}
|
||||
138
core/src/Classes/PasswordManager.php
Normal file
138
core/src/Classes/PasswordManager.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
use Classes\Crypt\AesCtr;
|
||||
use Users\Common\Model\User;
|
||||
use Utils\CalendarTools;
|
||||
|
||||
class PasswordManager
|
||||
{
|
||||
public static function verifyPassword($password, $hash)
|
||||
{
|
||||
$result = password_verify($password, $hash);
|
||||
if ($result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strlen($hash) === 32) {
|
||||
return md5($password) === $hash;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function createPasswordHash($password)
|
||||
{
|
||||
return password_hash($password, PASSWORD_BCRYPT, ['cost' => 13]);
|
||||
}
|
||||
|
||||
public static function passwordChangeWaitingTimeMinutes($user)
|
||||
{
|
||||
if (empty($user->last_password_requested_at)) {
|
||||
$user->last_password_requested_at = date('Y-m-d H:i:s');
|
||||
$user->Save();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$diff = CalendarTools::getTimeDiffInMinutes($user->last_password_requested_at, date('Y-m-d H:i:s'));
|
||||
if ($diff < 1) {
|
||||
return ceil($diff);
|
||||
}
|
||||
|
||||
$user->last_password_requested_at = date('Y-m-d H:i:s');
|
||||
$user->Save();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function createPasswordRestKey($user)
|
||||
{
|
||||
$newPassHash = array();
|
||||
$newPassHash["client"] = CLIENT_NAME;
|
||||
$newPassHash["email"] = $user->email;
|
||||
$newPassHash["time"] = date('Y-m-d H:i:s');
|
||||
$json = json_encode($newPassHash);
|
||||
|
||||
$encJson = AesCtr::encrypt($json, $user->password, 256);
|
||||
|
||||
return urlencode(AesCtr::encrypt($user->id, APP_PASSWORD, 256).'-'.$encJson);
|
||||
}
|
||||
|
||||
public static function verifyPasswordRestKey($key)
|
||||
{
|
||||
$arr = explode("-", $key);
|
||||
$userId = AesCtr::decrypt($arr[0], APP_PASSWORD, 256);
|
||||
$user = new User();
|
||||
$user->Load("id = ?", array($userId));
|
||||
|
||||
if (empty($user->id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
array_shift($arr);
|
||||
$data = AesCtr::decrypt(implode('', $arr), $user->password, 256);
|
||||
|
||||
if (empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = json_decode($data, true);
|
||||
|
||||
if (empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($data['client'] != CLIENT_NAME || $data['email'] != $user->email) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CalendarTools::getTimeDiffInMinutes($data['time'], date('Y-m-d H:i:s')) < 30) {
|
||||
return $user;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function isQualifiedPassword($password)
|
||||
{
|
||||
if (strlen($password) < 8) {
|
||||
$error = "Password too short";
|
||||
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
}
|
||||
|
||||
if (strlen($password) > 20) {
|
||||
$error = "Password too long";
|
||||
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
}
|
||||
|
||||
if (!preg_match("#[0-9]+#", $password)) {
|
||||
$error = "Password must include at least one number";
|
||||
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
}
|
||||
|
||||
if (!preg_match("#[a-z]+#", $password)) {
|
||||
$error = "Password must include at least one lowercase letter";
|
||||
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
}
|
||||
|
||||
if (!preg_match("#[A-Z]+#", $password)) {
|
||||
$error = "Password must include at least one uppercase letter";
|
||||
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
}
|
||||
|
||||
if (!preg_match("#\W+#", $password)) {
|
||||
$error = "Password must include at least one symbol";
|
||||
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
}
|
||||
|
||||
return new IceResponse(IceResponse::SUCCESS);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,13 @@ use Model\BaseModel;
|
||||
|
||||
class PermissionManager
|
||||
{
|
||||
const RESTRICTED_USER_LEVELS = ['Restricted Admin', 'Restricted Manager', 'Restricted Employee'];
|
||||
|
||||
public function isRestrictedUserLevel($userLevel)
|
||||
{
|
||||
return in_array($userLevel, self::RESTRICTED_USER_LEVELS);
|
||||
}
|
||||
|
||||
public static function manipulationAllowed($employeeId, BaseModel $object)
|
||||
{
|
||||
$subIds = self::getSubordinateIds($employeeId, $object->allowIndirectMapping());
|
||||
|
||||
106
core/src/Classes/RedisCacheService.php
Normal file
106
core/src/Classes/RedisCacheService.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
use Predis\Client;
|
||||
|
||||
class RedisCacheService implements CacheService
|
||||
{
|
||||
protected $client = null;
|
||||
protected $appName = null;
|
||||
|
||||
public function __construct($uri, $appName)
|
||||
{
|
||||
$this->uri = $uri;
|
||||
$this->appName = $appName;
|
||||
}
|
||||
|
||||
protected function getClient()
|
||||
{
|
||||
if ($this->client === null && !empty($this->uri)) {
|
||||
$this->client = new Client($this->uri);
|
||||
}
|
||||
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
protected function getAppKey($keyData)
|
||||
{
|
||||
return sprintf('%s-%s', $this->appName, implode('-', $keyData));
|
||||
}
|
||||
|
||||
|
||||
public function setDBQuery($entity, $query, $params, $result, $ttl = 600)
|
||||
{
|
||||
/** @var Client $client */
|
||||
$client = $this->getClient();
|
||||
if ($client == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$client->set($this->getAppKey([$entity, $query, implode('-', $params)]), base64_encode(serialize($result)));
|
||||
$client->expire($this->getAppKey([$query, $params]), $ttl);
|
||||
}
|
||||
|
||||
public function getDBQuery($entity, $query, $params)
|
||||
{
|
||||
/** @var Client $client */
|
||||
$client = $this->getClient();
|
||||
if ($client == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$base64 = $client->get($this->getAppKey([$entity, $query, implode('-', $params)]));
|
||||
if (empty($base64)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = unserialize(base64_decode($base64));
|
||||
|
||||
if (empty($data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function deleteDatabaseEntity($table, $id)
|
||||
{
|
||||
/** @var Client $client */
|
||||
$client = $this->getClient();
|
||||
if ($client == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$client->del([$this->getAppKey([$table, $id])]);
|
||||
}
|
||||
|
||||
public function deleteQuery($query)
|
||||
{
|
||||
/** @var Client $client */
|
||||
$client = $this->getClient();
|
||||
if ($client == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$client->del([$this->getAppKey([$query])]);
|
||||
}
|
||||
|
||||
protected function deleteByPrefix($prefix)
|
||||
{
|
||||
/** @var Client $client */
|
||||
$client = $this->getClient();
|
||||
if ($client == null) {
|
||||
return null;
|
||||
}
|
||||
$list = $client->keys($this->getAppKey([$prefix]).'*');
|
||||
if (!empty($list)) {
|
||||
$client->del($list);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteByEntity($entity)
|
||||
{
|
||||
$this->deleteByPrefix($entity.'-');
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,38 @@ use Classes\Data\DataReader;
|
||||
use Classes\Data\Query\DataQuery;
|
||||
use Classes\Upload\Uploader;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Model\BaseModel;
|
||||
use Users\Common\Model\User;
|
||||
use Utils\SessionUtils;
|
||||
|
||||
class RestEndPoint
|
||||
{
|
||||
/*
|
||||
200
|
||||
GET/PUT
|
||||
Response entity details or list of entities.
|
||||
|
||||
201
|
||||
POST
|
||||
To create a new entity.
|
||||
|
||||
400
|
||||
GET/POST/PUT/DELETE
|
||||
Request payload and query params validation error
|
||||
|
||||
401
|
||||
GET/POST/PUT/DELETE
|
||||
Authentication error
|
||||
|
||||
403
|
||||
GET/POST/PUT/DELETE
|
||||
Authorization issue
|
||||
|
||||
404
|
||||
GET/POST/PUT/DELETE
|
||||
We don’t have the endpoint
|
||||
|
||||
*/
|
||||
const RESPONSE_ERR_ENTITY_NOT_FOUND = 'Entity not found';
|
||||
const RESPONSE_ERR_PERMISSION_DENIED = 'Permission denied';
|
||||
const RESPONSE_ERR_UNPROCESSABLE = 'Unprocessable Entity';
|
||||
@@ -19,6 +46,8 @@ class RestEndPoint
|
||||
|
||||
const ELEMENT_NAME = '';
|
||||
|
||||
protected $cachedObjects = [];
|
||||
|
||||
public function getModelObject($id)
|
||||
{
|
||||
return false;
|
||||
@@ -56,21 +85,38 @@ class RestEndPoint
|
||||
return new IceResponse(IceResponse::SUCCESS);
|
||||
}
|
||||
|
||||
public function process($type, $parameters = [])
|
||||
public function process($type, $parameters = [], $requireAccessToken = true)
|
||||
{
|
||||
if ($parameters === null) {
|
||||
$parameters = [];
|
||||
}
|
||||
|
||||
if (!is_array($parameters)) {
|
||||
$parameters = [$parameters];
|
||||
}
|
||||
$accessTokenValidation = $this->validateAccessToken();
|
||||
if (!empty($accessTokenValidation) && $accessTokenValidation->getStatus() == IceResponse::ERROR) {
|
||||
$resp = $accessTokenValidation;
|
||||
} else {
|
||||
|
||||
if ($requireAccessToken) {
|
||||
$accessTokenValidation = $this->validateAccessToken();
|
||||
if (!empty($accessTokenValidation) && $accessTokenValidation->getStatus() == IceResponse::ERROR) {
|
||||
$resp = $accessTokenValidation;
|
||||
|
||||
return $this->sendResponse($resp);
|
||||
}
|
||||
|
||||
BaseService::getInstance()->setCurrentUser($accessTokenValidation->getData());
|
||||
SessionUtils::saveSessionObject('user', $accessTokenValidation->getData());
|
||||
array_unshift($parameters, $accessTokenValidation->getData());
|
||||
$resp = call_user_func_array(array($this, $type), $parameters);
|
||||
} else {
|
||||
array_unshift($parameters, new User());
|
||||
}
|
||||
|
||||
$resp = call_user_func_array(array($this, $type), $parameters);
|
||||
|
||||
return $this->sendResponse($resp);
|
||||
}
|
||||
|
||||
protected function sendResponse($resp)
|
||||
{
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($resp->getStatus() == IceResponse::SUCCESS && $resp->getCode() == null) {
|
||||
@@ -91,25 +137,64 @@ class RestEndPoint
|
||||
);
|
||||
$this->printResponse(array("error" => [$messages]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BaseModel $obj
|
||||
* @param $map
|
||||
* @return mixed
|
||||
*/
|
||||
protected function enrichElement($obj, $map)
|
||||
{
|
||||
if (!empty($map)) {
|
||||
foreach ($map as $k => $v) {
|
||||
if ($obj->$k !== null) {
|
||||
$obj->$k = [
|
||||
'type' => $v[0],
|
||||
$v[1] => $obj->$k,
|
||||
'display' => $obj->{$k . '_Name'}
|
||||
];
|
||||
} else {
|
||||
unset($obj->$k);
|
||||
}
|
||||
unset($obj->{$k . '_Name'});
|
||||
if (empty($map)) {
|
||||
return $obj;
|
||||
}
|
||||
|
||||
foreach ($map as $k => $v) {
|
||||
$fTable = BaseService::getInstance()->getFullQualifiedModelClassName($v[0]);
|
||||
$tObj = new $fTable();
|
||||
$tObjArr = $tObj->Find($v[1] . "= ?", [$obj->$k], true);
|
||||
if (!is_array($tObjArr) || empty($tObjArr[0])) {
|
||||
continue;
|
||||
}
|
||||
$obj->$k = [
|
||||
'type' => $v[0],
|
||||
$v[1] => $obj->$k,
|
||||
'display' => $this->getCombinedValue($v[2], $tObjArr[0])
|
||||
];
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
protected function enrichElements($items, $map)
|
||||
{
|
||||
return array_map(function ($item) use ($map) {
|
||||
return $this->enrichElement($item, $map);
|
||||
}, $items);
|
||||
}
|
||||
|
||||
protected function getCombinedValue($nameField, $targetObject)
|
||||
{
|
||||
$values = explode("+", $nameField);
|
||||
if (count($values) == 1) {
|
||||
return $targetObject->{$nameField};
|
||||
}
|
||||
$objVal = '';
|
||||
foreach ($values as $value) {
|
||||
if ($objVal != "") {
|
||||
$objVal .= " ";
|
||||
}
|
||||
if (substr($value, 0, 1) !== ':') {
|
||||
$objVal .= $targetObject->{$value};
|
||||
} else {
|
||||
$objVal .= substr($value, 1);
|
||||
}
|
||||
}
|
||||
return $obj;
|
||||
|
||||
return $objVal;
|
||||
}
|
||||
|
||||
protected function cleanObject($obj)
|
||||
@@ -164,6 +249,10 @@ class RestEndPoint
|
||||
$output = array();
|
||||
$columns = $query->getColumns();
|
||||
foreach ($data as $item) {
|
||||
if (!empty($query->getFieldMapping())) {
|
||||
$map = json_decode($query->getFieldMapping(), true);
|
||||
$item = $this->enrichElement($item, $map);
|
||||
}
|
||||
if (!empty($columns)) {
|
||||
$obj = new \stdClass();
|
||||
foreach ($columns as $column) {
|
||||
|
||||
@@ -37,6 +37,7 @@ class S3FileSystem
|
||||
));
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->error($e->getMessage());
|
||||
LogManager::getInstance()->error($e);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -60,7 +61,8 @@ class S3FileSystem
|
||||
'Key' => $key
|
||||
));
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->info($e->getMessage());
|
||||
LogManager::getInstance()->error($e->getMessage());
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ class UIManager
|
||||
}
|
||||
|
||||
$menuItems[] = new MenuItemTemplate('menuButtonNotification', array());
|
||||
if ($this->user->user_level == "Admin") {
|
||||
if ($this->user->user_level == 'Admin') {
|
||||
$menuItems[] = new MenuItemTemplate('menuButtonSwitchProfile', array());
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ class UIManager
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->user->user_level == "Admin") {
|
||||
if ($this->user->user_level == 'Admin') {
|
||||
$other = '';
|
||||
if (class_exists('\\Classes\\ProVersion')) {
|
||||
$pro = new ProVersion();
|
||||
|
||||
29
core/src/Classes/Upload/TempFile.php
Normal file
29
core/src/Classes/Upload/TempFile.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Classes\Upload;
|
||||
|
||||
class TempFile
|
||||
{
|
||||
protected $data;
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function save($path)
|
||||
{
|
||||
if (!move_uploaded_file($this->data['file']['tmp_name'], $path)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->data['file']['name'];
|
||||
}
|
||||
|
||||
public function getSize()
|
||||
{
|
||||
return $this->data['file']['size'];
|
||||
}
|
||||
}
|
||||
159
core/src/Classes/Upload/Uploader.php
Normal file
159
core/src/Classes/Upload/Uploader.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
namespace Classes\Upload;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\FileService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\S3FileSystem;
|
||||
use Classes\SettingsManager;
|
||||
use Model\File;
|
||||
use Utils\LogManager;
|
||||
|
||||
class Uploader
|
||||
{
|
||||
private $allowedExtensions = array();
|
||||
private $sizeLimit = 10485760;
|
||||
|
||||
private $file;
|
||||
|
||||
public function __construct($file, array $allowedExtensions = array(), $sizeLimit = 10485760)
|
||||
{
|
||||
$allowedExtensions = array_map("strtolower", $allowedExtensions);
|
||||
$this->allowedExtensions = $allowedExtensions;
|
||||
$this->sizeLimit = $sizeLimit;
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
|
||||
protected function handleUpload($uploadDirectory, $saveFileName, $replaceOldFile = false)
|
||||
{
|
||||
if (!is_writable($uploadDirectory)) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
"Server error. Upload directory ($uploadDirectory) is not writable"
|
||||
);
|
||||
}
|
||||
|
||||
if (!$this->file) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
'No files were uploaded.'
|
||||
);
|
||||
}
|
||||
|
||||
$size = $this->file->getSize();
|
||||
LogManager::getInstance()->info('file size ='.$size);
|
||||
LogManager::getInstance()->info('file size limit ='.$this->sizeLimit);
|
||||
if ($size == 0) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
'File is empty'
|
||||
);
|
||||
}
|
||||
|
||||
if ($size > $this->sizeLimit) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
'File is too large'
|
||||
);
|
||||
}
|
||||
|
||||
$pathinfo = pathinfo($this->file->getName());
|
||||
$ext = $pathinfo['extension'];
|
||||
|
||||
if ($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)) {
|
||||
$these = implode(', ', $this->allowedExtensions);
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
'File has an invalid extension, it should be one of '. $these . '.'
|
||||
);
|
||||
}
|
||||
|
||||
$saveFileName = $saveFileName.'.'.strtolower($ext);
|
||||
|
||||
$finalFileLocation = $uploadDirectory . $saveFileName;
|
||||
|
||||
if ($this->file->save($finalFileLocation)) {
|
||||
$arr = explode("/", $finalFileLocation);
|
||||
return new IceResponse(
|
||||
IceResponse::SUCCESS,
|
||||
$arr[count($arr)-1]
|
||||
);
|
||||
//return array('success'=>1,'filename'=>$arr[count($arr)-1],'error'=>'');
|
||||
} else {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
'The upload was cancelled, or server error encountered'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static function upload($postData, $fileData)
|
||||
{
|
||||
//Generate File Name
|
||||
$saveFileName = $postData['file_name'];
|
||||
$saveFileName = str_replace("..", "", $saveFileName);
|
||||
$saveFileName = str_replace("/", "", $saveFileName);
|
||||
|
||||
if (stristr($saveFileName, ".php")) {
|
||||
$saveFileName = str_replace(".php", "", $saveFileName);
|
||||
}
|
||||
|
||||
if (empty($saveFileName) || $saveFileName == "_NEW_") {
|
||||
$saveFileName = microtime();
|
||||
$saveFileName = str_replace(".", "", $saveFileName);
|
||||
$saveFileName = str_replace(" ", "", $saveFileName);
|
||||
}
|
||||
|
||||
$file = new File();
|
||||
$file->Load("name = ?", array($saveFileName));
|
||||
|
||||
$allowedExtensions = explode(',', "csv,doc,xls,docx,xlsx,txt,ppt,pptx,rtf,pdf,xml,jpg,bmp,gif,png,jpeg");
|
||||
// max file size in bytes
|
||||
$sizeLimit =MAX_FILE_SIZE_KB * 1024;
|
||||
$uploader = new Uploader(new TempFile($fileData), $allowedExtensions, $sizeLimit);
|
||||
$result = $uploader->handleUpload(CLIENT_BASE_PATH.'data/', $saveFileName);
|
||||
|
||||
if ($result->getStatus() !== IceResponse::SUCCESS) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
|
||||
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting("Files: Amazon S3 Key for File Upload");
|
||||
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
|
||||
"Files: Amazone S3 Secret for File Upload"
|
||||
);
|
||||
$s3Bucket = SettingsManager::getInstance()->getSetting("Files: S3 Bucket");
|
||||
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
|
||||
|
||||
$localFile = CLIENT_BASE_PATH.'data/'.$result->getData();
|
||||
$uploadedFileSize = filesize($localFile);
|
||||
if ($uploadFilesToS3.'' == '1' && !empty($uploadFilesToS3Key) && !empty($uploadFilesToS3Secret) &&
|
||||
!empty($s3Bucket) && !empty($s3WebUrl)) {
|
||||
$uploadName = CLIENT_NAME."/".$result->getData();
|
||||
LogManager::getInstance()->info("Upload file to s3:".$uploadName);
|
||||
LogManager::getInstance()->info("Local file:".$localFile);
|
||||
LogManager::getInstance()->info("Local file size:".$uploadedFileSize);
|
||||
|
||||
|
||||
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
|
||||
$res = $s3FileSys->putObject($s3Bucket, $uploadName, $localFile, 'authenticated-read');
|
||||
|
||||
LogManager::getInstance()->info("Response from s3 file sys:".print_r($res, true));
|
||||
unlink($localFile);
|
||||
}
|
||||
|
||||
$file->name = $saveFileName;
|
||||
$file->filename = $result->getData();
|
||||
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
|
||||
$file->$signInMappingField = $postData['user']=="_NONE_"?null:$postData['user'];
|
||||
$file->file_group = $postData['file_group'];
|
||||
$file->size = $uploadedFileSize;
|
||||
$file->size_text = FileService::getInstance()->getReadableSize($uploadedFileSize);
|
||||
$file->Save();
|
||||
return new IceResponse(
|
||||
IceResponse::SUCCESS,
|
||||
$saveFileName
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace Company\Common\Model;
|
||||
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Model\BaseModel;
|
||||
|
||||
@@ -16,7 +17,7 @@ class CompanyStructure extends BaseModel
|
||||
|
||||
public function getManagerAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getUserAccess()
|
||||
@@ -24,6 +25,14 @@ class CompanyStructure extends BaseModel
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('employees', 'user'),
|
||||
];
|
||||
}
|
||||
|
||||
public function validateSave($obj)
|
||||
{
|
||||
if ($obj->id == $obj->parent && !empty($obj->parent)) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace Company\Common\Model;
|
||||
|
||||
use Model\BaseModel;
|
||||
use Utils\LogManager;
|
||||
|
||||
class Timezone extends BaseModel
|
||||
{
|
||||
@@ -22,6 +23,11 @@ class Timezone extends BaseModel
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getAnonymousAccess()
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getTimezonesWithOffset()
|
||||
{
|
||||
$tz = new Timezone();
|
||||
@@ -34,6 +40,7 @@ class Timezone extends BaseModel
|
||||
$tz->details = sprintf("(%s) %s", $this->formatOffset($z->getOffset($c)), $tz->name);
|
||||
$modifiedTimeZones[] = $tz;
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ abstract class AbstractDataImporter implements DataImporter
|
||||
protected $columnsCompeted = array();
|
||||
protected $relatedColumns = array();
|
||||
|
||||
protected $status = IceResponse::SUCCESS;
|
||||
|
||||
public function getResult()
|
||||
{
|
||||
return $this->rowObjects;
|
||||
@@ -37,24 +39,48 @@ abstract class AbstractDataImporter implements DataImporter
|
||||
$columns = $this->dataImport->columns;
|
||||
$headers = json_decode($columns);
|
||||
|
||||
$counter = 0;
|
||||
$expectedColumnOrder = [];
|
||||
$actualColumnOrder = [];
|
||||
$headerValidationFailed = false;
|
||||
|
||||
if (count($headers) != count($data)) {
|
||||
if ($headerValidationFailed) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
[
|
||||
'Column count in the file do not match the header count'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($headers as $testColumn) {
|
||||
$expectedColumnOrder[] = $testColumn->name;
|
||||
$actualColumnOrder[] = $data[$counter];
|
||||
if (trim($testColumn->name) !== trim($data[$counter])) {
|
||||
$headerValidationFailed = true;
|
||||
}
|
||||
|
||||
$counter++;
|
||||
}
|
||||
|
||||
if ($headerValidationFailed) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
[
|
||||
'expected' => $expectedColumnOrder,
|
||||
'actual'=> $actualColumnOrder
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$counter = 0;
|
||||
foreach ($headers as $column) {
|
||||
$this->headerMapping[] = $column;
|
||||
if ($column->idField == "Yes") {
|
||||
$this->primaryKeyColumn = $counter;
|
||||
}
|
||||
//Update related columns
|
||||
if (($column->type == "Reference" || $column->type == "Attached") && $column->isKeyField == "Yes") {
|
||||
$this->relatedColumns[$counter] = array();
|
||||
for ($i = 0; $i< count($headers); $i++) {
|
||||
$columnNew = $headers[$i];
|
||||
if ($columnNew->id != $column->id &&
|
||||
$columnNew->dependOn == $column->dependOn && $column->dependOn != "NULL") {
|
||||
$this->relatedColumns[$counter][$i] = $columnNew;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$counter++;
|
||||
}
|
||||
|
||||
@@ -63,6 +89,7 @@ abstract class AbstractDataImporter implements DataImporter
|
||||
$this->objectKeys = $obj->getObjectKeys();
|
||||
|
||||
$this->updateCustomFields();
|
||||
return new IceResponse(IceResponse::SUCCESS);
|
||||
}
|
||||
|
||||
public function setDataImportId($dataImportId)
|
||||
@@ -74,26 +101,13 @@ abstract class AbstractDataImporter implements DataImporter
|
||||
public function updateCustomFields()
|
||||
{
|
||||
$customField = new CustomField();
|
||||
$customFields = $customField->Find("type = ?", array($this->getModelObject()));
|
||||
$customFields = $customField->Find("type = ?", array($this->getModelObjectName()));
|
||||
$this->customFields = array();
|
||||
foreach ($customFields as $cf) {
|
||||
$this->customFields[$cf->name] = $cf;
|
||||
}
|
||||
}
|
||||
|
||||
public function addCustomField($column)
|
||||
{
|
||||
$customField = new CustomField();
|
||||
$customField->type = $this->getModelObject();
|
||||
$customField->name = $column->name;
|
||||
$customField->display = "Form";
|
||||
$customField->field_type = "text";
|
||||
$customField->field_label = $column->title;
|
||||
$customField->field_validation = "none";
|
||||
$customField->display_order = 0;
|
||||
$customField->Save();
|
||||
}
|
||||
|
||||
public function markCellCompleted($row, $col)
|
||||
{
|
||||
if (!isset($this->columnsCompeted[$row])) {
|
||||
@@ -136,48 +150,15 @@ abstract class AbstractDataImporter implements DataImporter
|
||||
}
|
||||
}
|
||||
|
||||
//Check for non existing column names
|
||||
if (!isset($this->objectKeys[$headerColumn->name])) {
|
||||
if (!isset($this->customFields[$headerColumn->name])) {
|
||||
$this->addCustomField($headerColumn);
|
||||
$this->updateCustomFields();
|
||||
}
|
||||
}
|
||||
|
||||
if ($headerColumn->type == "Normal") {
|
||||
$this->rowObjects[$row]->{$headerColumn->name} = $data;
|
||||
} elseif ($headerColumn->type == "Reference" || $headerColumn->type == "Attached") {
|
||||
if ($headerColumn->isKeyField == "Yes") {
|
||||
$hcClass = BaseService::getInstance()->getFullQualifiedModelClassName($headerColumn->dependOn);
|
||||
$hcField = $headerColumn->dependOnField;
|
||||
/* @var \Model\BaseModel $hcObject */
|
||||
$hcObject = new $hcClass();
|
||||
if ($headerColumn->type == "Attached" && !empty($this->rowObjects[$row]->id)) {
|
||||
$hcObject->Load("$hcField = ? and employee = ?", array($data,$this->rowObjects[$row]->id));
|
||||
} else {
|
||||
$hcObject->Load("$hcField = ?", array($data));
|
||||
}
|
||||
|
||||
$hcObject->{$hcField} = $data;
|
||||
foreach ($this->relatedColumns[$column] as $key => $val) {
|
||||
$tempValName = $val->name;
|
||||
if (strstr($val->name, "/")) {
|
||||
$tempValName = explode("/", $val->name)[1];
|
||||
}
|
||||
$hcObject->{$tempValName} = $allData[$key];
|
||||
$this->markCellCompleted($row, $key);
|
||||
}
|
||||
|
||||
if ($headerColumn->type == "Reference") {
|
||||
$hcObject->Save();
|
||||
} else {
|
||||
if (!isset($this->attachedObjects[$row])) {
|
||||
$this->attachedObjects[$row] = array();
|
||||
}
|
||||
$this->attachedObjects[$row][] = $hcObject;
|
||||
}
|
||||
$this->rowObjects[$row]->{$headerColumn->name} = $hcObject->id;
|
||||
}
|
||||
} elseif ($headerColumn->type == "Reference") {
|
||||
$hcClass = BaseService::getInstance()->getFullQualifiedModelClassName($headerColumn->dependOn);
|
||||
$hcField = $headerColumn->dependOnField;
|
||||
/* @var \Model\BaseModel $hcObject */
|
||||
$hcObject = new $hcClass();
|
||||
$hcObject->Load("$hcField = ?", array($data));
|
||||
$this->rowObjects[$row]->{$headerColumn->name} = $hcObject->id;
|
||||
}
|
||||
|
||||
$this->markCellCompleted($row, $column);
|
||||
@@ -215,20 +196,10 @@ abstract class AbstractDataImporter implements DataImporter
|
||||
foreach ($this->rowObjects[$row] as $k => $v) {
|
||||
if (isset($customFields[$k])) {
|
||||
BaseService::getInstance()->customFieldManager
|
||||
->addCustomField($class, $this->rowObjects[$row]->id, $k, $v);
|
||||
->addCustomField($this->getModelObjectName(), $this->rowObjects[$row]->id, $k, $v);
|
||||
$result['CustomFields'][] = array($class, $this->rowObjects[$row]->id, $k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->attachedObjects[$row])) {
|
||||
/* @var \Model\BaseModel $aObj */
|
||||
foreach ($this->attachedObjects[$row] as $aObj) {
|
||||
$aObj->employee = $this->rowObjects[$row]->id;
|
||||
|
||||
$aObj->Save();
|
||||
$result['attachedObjects'][] = $aObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result['Error'] = "Duplicate Object Found";
|
||||
@@ -238,6 +209,10 @@ abstract class AbstractDataImporter implements DataImporter
|
||||
}
|
||||
|
||||
abstract public function getModelObject();
|
||||
abstract public function getModelObjectName();
|
||||
public function setModelObjectName($name)
|
||||
{
|
||||
}
|
||||
public function isDuplicate($obj)
|
||||
{
|
||||
return false;
|
||||
@@ -264,7 +239,12 @@ abstract class AbstractDataImporter implements DataImporter
|
||||
$cells = str_getcsv($line, ",");
|
||||
if ($headerProcessed === false) {
|
||||
$this->setDataImportId($dataImportId);
|
||||
$this->processHeader($cells);
|
||||
$result = $this->processHeader($cells);
|
||||
if ($result->getStatus() === IceResponse::ERROR) {
|
||||
$this->status = IceResponse::ERROR;
|
||||
$this->rowObjects = $result->getData();
|
||||
return $result->getData();
|
||||
}
|
||||
$headerProcessed = true;
|
||||
} else {
|
||||
$result = $this->processDataRow($counter, $cells);
|
||||
@@ -278,6 +258,6 @@ abstract class AbstractDataImporter implements DataImporter
|
||||
|
||||
public function getLastStatus()
|
||||
{
|
||||
return IceResponse::SUCCESS;
|
||||
return $this->status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +44,12 @@ class DataActionManager extends SubActionManager
|
||||
|
||||
$processClass = '\\Data\Admin\Import\\'.$dataImport->dataType;
|
||||
$processObj = new $processClass();
|
||||
|
||||
$processObj->setModelObjectName($dataImport->objectType);
|
||||
$res = $processObj->process($data, $dataImport->id);
|
||||
if ($processObj->getLastStatus() === IceResponse::SUCCESS) {
|
||||
$dataFile->status = "Processed";
|
||||
} else {
|
||||
$dataFile->status = "Failed";
|
||||
}
|
||||
$dataFile->details = json_encode($res, JSON_PRETTY_PRINT);
|
||||
$dataFile->Save();
|
||||
@@ -57,4 +59,29 @@ class DataActionManager extends SubActionManager
|
||||
private function processHeader($dataImportId, $data)
|
||||
{
|
||||
}
|
||||
|
||||
public function downloadTemplate($req)
|
||||
{
|
||||
$dataImport = new DataImport();
|
||||
$dataImport->Load("id =?", array($req->id));
|
||||
|
||||
$columns = json_decode($dataImport->columns);
|
||||
|
||||
$headers = [];
|
||||
$sample = [];
|
||||
|
||||
foreach ($columns as $column) {
|
||||
$headers[] = $column->name;
|
||||
$sample[] = $column->sampleValue;
|
||||
}
|
||||
|
||||
$output = fopen('php://output', 'w');
|
||||
header('Content-Type:application/csv');
|
||||
header('Content-Disposition:attachment;filename='.$dataImport->name.'.csv');
|
||||
fputcsv($output, $headers);
|
||||
fputcsv($output, $sample);
|
||||
fclose($output);
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@ class AttendanceDataImporter extends AbstractDataImporter
|
||||
return "\\Attendance\\Common\\Model\\Attendance";
|
||||
}
|
||||
|
||||
public function getModelObjectName()
|
||||
{
|
||||
return 'Attendance';
|
||||
}
|
||||
|
||||
public function fixBeforeSave($object, $data)
|
||||
{
|
||||
return $object;
|
||||
|
||||
34
core/src/Data/Admin/Import/CommonDataImporter.php
Normal file
34
core/src/Data/Admin/Import/CommonDataImporter.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Data\Admin\Import;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Data\Admin\Api\AbstractDataImporter;
|
||||
|
||||
class CommonDataImporter extends AbstractDataImporter
|
||||
{
|
||||
|
||||
protected $processed = array();
|
||||
protected $modelObjectName;
|
||||
|
||||
public function getModelObject()
|
||||
{
|
||||
return BaseService::getInstance()->getFullQualifiedModelClassName($this->modelObjectName);
|
||||
}
|
||||
|
||||
public function getModelObjectName()
|
||||
{
|
||||
return $this->modelObjectName;
|
||||
}
|
||||
|
||||
public function setModelObjectName($name)
|
||||
{
|
||||
return $this->modelObjectName = $name;
|
||||
}
|
||||
|
||||
public function fixBeforeSave($object, $data)
|
||||
{
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,11 @@ class EmployeeDataImporter extends AbstractDataImporter
|
||||
return "\\Employees\\Common\\Model\\Employee";
|
||||
}
|
||||
|
||||
public function getModelObjectName()
|
||||
{
|
||||
return 'Employee';
|
||||
}
|
||||
|
||||
public function fixBeforeSave($object, $data)
|
||||
{
|
||||
|
||||
|
||||
@@ -315,4 +315,8 @@ class PayrollDataImporter implements DataImporter
|
||||
{
|
||||
return $this->lastStatus;
|
||||
}
|
||||
|
||||
public function setModelObjectName($name)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
30
core/src/Data/Admin/Import/UserDataImporter.php
Normal file
30
core/src/Data/Admin/Import/UserDataImporter.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Data\Admin\Import;
|
||||
|
||||
use Data\Admin\Api\AbstractDataImporter;
|
||||
|
||||
class UserDataImporter extends AbstractDataImporter
|
||||
{
|
||||
|
||||
protected $processed = array();
|
||||
|
||||
public function getModelObject()
|
||||
{
|
||||
return "\\Users\\Common\\Model\\User";
|
||||
}
|
||||
|
||||
public function getModelObjectName()
|
||||
{
|
||||
return 'User';
|
||||
}
|
||||
|
||||
public function fixBeforeSave($object, $data)
|
||||
{
|
||||
if (empty($object->password)) {
|
||||
$object->password = md5($object->password);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Data\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class DataImport extends BaseModel
|
||||
@@ -16,4 +17,11 @@ class DataImport extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('data', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace Data\Common\Model;
|
||||
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class DataImportFile extends BaseModel
|
||||
@@ -25,4 +26,11 @@ class DataImportFile extends BaseModel
|
||||
}
|
||||
return new IceResponse(IceResponse::SUCCESS, $obj);
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('data', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Dependents\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class EmployeeDependent extends BaseModel
|
||||
@@ -27,4 +28,12 @@ class EmployeeDependent extends BaseModel
|
||||
{
|
||||
return array("element","save","delete");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('employees', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
34
core/src/Documents/Admin/Api/DocumentsAdminManager.php
Normal file
34
core/src/Documents/Admin/Api/DocumentsAdminManager.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace Documents\Admin\Api;
|
||||
|
||||
use Classes\AbstractModuleManager;
|
||||
|
||||
class DocumentsAdminManager extends AbstractModuleManager
|
||||
{
|
||||
|
||||
public function initializeUserClasses()
|
||||
{
|
||||
}
|
||||
|
||||
public function initializeFieldMappings()
|
||||
{
|
||||
$this->addFileFieldMapping('EmployeeDocument', 'attachment', 'name');
|
||||
}
|
||||
|
||||
public function initializeDatabaseErrorMappings()
|
||||
{
|
||||
$this->addDatabaseErrorMapping(
|
||||
'CONSTRAINT `Fk_EmployeeDocuments_Documents` FOREIGN KEY',
|
||||
'Can not delete Document Type, users have already uploaded these types of documents'
|
||||
);
|
||||
}
|
||||
|
||||
public function setupModuleClassDefinitions()
|
||||
{
|
||||
|
||||
$this->addModelClass('Document');
|
||||
$this->addModelClass('CompanyDocument');
|
||||
$this->addModelClass('EmployeeDocument');
|
||||
$this->addModelClass('EmployeeDocumentNotification');
|
||||
}
|
||||
}
|
||||
103
core/src/Documents/Common/Model/CompanyDocument.php
Normal file
103
core/src/Documents/Common/Model/CompanyDocument.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/19/17
|
||||
* Time: 8:25 AM
|
||||
*/
|
||||
|
||||
namespace Documents\Common\Model;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\FileService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Model\BaseModel;
|
||||
|
||||
class CompanyDocument extends BaseModel
|
||||
{
|
||||
public $table = 'CompanyDocuments';
|
||||
|
||||
public function getAdminAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getManagerAccess()
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getUserAccess()
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('documents', 'admin'),
|
||||
new ModuleAccess('documents', 'user'),
|
||||
];
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
public function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
$res = parent::Find($whereOrderBy, $bindarr, $pkeysArr, $extra);
|
||||
|
||||
$user = BaseService::getInstance()->getCurrentUser();
|
||||
if ($user->user_level == 'Admin') {
|
||||
foreach ($res as $entry) {
|
||||
$file = FileService::getInstance()->getFileData($entry->attachment);
|
||||
$entry->type = $file->type;
|
||||
$entry->size = $file->size_text;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
$emp = BaseService::getInstance()->getCurrentProfileId();
|
||||
$employee = new Employee();
|
||||
$employee->Load("id = ?", array($emp));
|
||||
|
||||
$data = array();
|
||||
|
||||
foreach ($res as $entry) {
|
||||
if ($entry->status != 'Active') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$file = FileService::getInstance()->getFileData($entry->attachment);
|
||||
$entry->type = $file->type;
|
||||
$entry->size = $file->size_text;
|
||||
|
||||
if (!empty($entry->share_departments)) {
|
||||
$shareDepartments = json_decode($entry->share_departments, true);
|
||||
if (count($shareDepartments) == 1 && $shareDepartments[0] == "NULL") {
|
||||
//Shared with All Departments
|
||||
$data[] = $entry;
|
||||
continue;
|
||||
} else {
|
||||
if (in_array($employee->department, $shareDepartments)) {
|
||||
//Document is shared with employee's department
|
||||
$data[] = $entry;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($entry->share_employees)) {
|
||||
$shareEmployees = json_decode($entry->share_employees, true);
|
||||
if (in_array($employee->id, $shareEmployees)) {
|
||||
//Document is shared with the employee
|
||||
$data[] = $entry;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
29
core/src/Documents/Common/Model/Document.php
Normal file
29
core/src/Documents/Common/Model/Document.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Documents\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class Document extends BaseModel
|
||||
{
|
||||
public $table = 'Documents';
|
||||
|
||||
public function getAdminAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getManagerAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('documents', 'admin'),
|
||||
new ModuleAccess('documents', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
69
core/src/Documents/Common/Model/EmployeeDocument.php
Normal file
69
core/src/Documents/Common/Model/EmployeeDocument.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/19/17
|
||||
* Time: 8:26 AM
|
||||
*/
|
||||
|
||||
namespace Documents\Common\Model;
|
||||
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class EmployeeDocument extends BaseModel
|
||||
{
|
||||
public $table = 'EmployeeDocuments';
|
||||
|
||||
public function getAdminAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getManagerAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getUserAccess()
|
||||
{
|
||||
return array("get");
|
||||
}
|
||||
|
||||
public function getUserOnlyMeAccess()
|
||||
{
|
||||
return array("element","save","delete");
|
||||
}
|
||||
// @codingStandardsIgnoreStart
|
||||
public function Insert()
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
if (empty($this->date_added)) {
|
||||
$this->date_added = date("Y-m-d H:i:s");
|
||||
}
|
||||
return parent::Insert();
|
||||
}
|
||||
|
||||
public function executePreSaveActions($obj)
|
||||
{
|
||||
$obj->expire_notification_last = -1;
|
||||
return new IceResponse(IceResponse::SUCCESS, $obj);
|
||||
}
|
||||
|
||||
public function executePreUpdateActions($obj)
|
||||
{
|
||||
$obj->expire_notification_last = -1;
|
||||
return new IceResponse(IceResponse::SUCCESS, $obj);
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('employees', 'user'),
|
||||
new ModuleAccess('documents', 'admin'),
|
||||
new ModuleAccess('documents', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
namespace Documents\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class EmployeeDocumentNotification extends BaseModel
|
||||
{
|
||||
public $table = 'EmployeeDocumentNotifications';
|
||||
|
||||
public function getAdminAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getManagerAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getUserAccess()
|
||||
{
|
||||
return array("get");
|
||||
}
|
||||
|
||||
public function getUserOnlyMeAccess()
|
||||
{
|
||||
return array("element","save","delete");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('employees', 'user'),
|
||||
new ModuleAccess('documents', 'admin'),
|
||||
new ModuleAccess('documents', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
27
core/src/Documents/User/Api/DocumentsModulesManager.php
Normal file
27
core/src/Documents/User/Api/DocumentsModulesManager.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace Documents\User\Api;
|
||||
|
||||
use Classes\AbstractModuleManager;
|
||||
|
||||
class DocumentsModulesManager extends AbstractModuleManager
|
||||
{
|
||||
|
||||
public function initializeUserClasses()
|
||||
{
|
||||
if (defined('MODULE_TYPE') && MODULE_TYPE != 'admin') {
|
||||
$this->addUserClass("EmployeeDocument");
|
||||
}
|
||||
}
|
||||
|
||||
public function initializeFieldMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function initializeDatabaseErrorMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function setupModuleClassDefinitions()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace EmergencyContacts\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class EmergencyContact extends BaseModel
|
||||
@@ -26,4 +27,12 @@ class EmergencyContact extends BaseModel
|
||||
{
|
||||
return array("element","save","delete");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('employees', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
101
core/src/Employees/Admin/Api/EmployeeUtil.php
Normal file
101
core/src/Employees/Admin/Api/EmployeeUtil.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
namespace Employees\Admin\Api;
|
||||
|
||||
use Classes\BaseService;
|
||||
|
||||
class EmployeeUtil
|
||||
{
|
||||
public function getEmployeeDataField($employeeId, $startDate, $endDate, $field)
|
||||
{
|
||||
$employee = BaseService::getInstance()->getElement(
|
||||
'Employee',
|
||||
$employeeId,
|
||||
$this->getMapping(),
|
||||
true
|
||||
);
|
||||
return [
|
||||
'string',
|
||||
$employee->$field
|
||||
];
|
||||
}
|
||||
|
||||
public function getMapping()
|
||||
{
|
||||
$mapping = <<<JSON
|
||||
{
|
||||
"nationality":[
|
||||
"Nationality",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"ethnicity":[
|
||||
"Ethnicity",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"immigration_status":[
|
||||
"ImmigrationStatus",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"employment_status":[
|
||||
"EmploymentStatus",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"job_title":[
|
||||
"JobTitle",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"pay_grade":[
|
||||
"PayGrade",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"country":[
|
||||
"Country",
|
||||
"code",
|
||||
"name"
|
||||
],
|
||||
"province":[
|
||||
"Province",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"department":[
|
||||
"CompanyStructure",
|
||||
"id",
|
||||
"title"
|
||||
],
|
||||
"supervisor":[
|
||||
"Employee",
|
||||
"id",
|
||||
"first_name+last_name"
|
||||
],
|
||||
"indirect_supervisors":[
|
||||
"Employee",
|
||||
"id",
|
||||
"first_name+last_name"
|
||||
],
|
||||
"approver1":[
|
||||
"Employee",
|
||||
"id",
|
||||
"first_name+last_name"
|
||||
],
|
||||
"approver2":[
|
||||
"Employee",
|
||||
"id",
|
||||
"first_name+last_name"
|
||||
],
|
||||
"approver3":[
|
||||
"Employee",
|
||||
"id",
|
||||
"first_name+last_name"
|
||||
]
|
||||
}
|
||||
JSON;
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ use Salary\Common\Model\EmployeeSalary;
|
||||
use TimeSheets\Common\Model\EmployeeTimeEntry;
|
||||
use TimeSheets\Common\Model\EmployeeTimeSheet;
|
||||
use Travel\Common\Model\EmployeeTravelRecord;
|
||||
use Utils\LogManager;
|
||||
|
||||
class EmployeesActionManager extends SubActionManager
|
||||
{
|
||||
@@ -63,7 +64,6 @@ class EmployeesActionManager extends SubActionManager
|
||||
|
||||
$employee->termination_date = null;
|
||||
$employee->status = 'Active';
|
||||
|
||||
$ok = $employee->Save();
|
||||
if (!$ok) {
|
||||
return new IceResponse(IceResponse::ERROR, "Error occurred while activating employee");
|
||||
@@ -113,7 +113,13 @@ class EmployeesActionManager extends SubActionManager
|
||||
|
||||
$data->timesheets = $this->getEmployeeData($employee->id, new EmployeeTimeSheet());
|
||||
$data->timesheetEntries = $this->getEmployeeData($employee->id, new EmployeeTimeEntry());
|
||||
$data->attendance = $this->getEmployeeData($employee->id, new Attendance());
|
||||
|
||||
$attendnace = $this->getEmployeeData($employee->id, new Attendance());
|
||||
$data->attendance = array_map(function ($item) {
|
||||
$item->image_in = '';
|
||||
$item->image_out = '';
|
||||
}, $attendnace);
|
||||
|
||||
if (class_exists('\Documents\Common\Model\EmployeeDocument')) {
|
||||
$data->documents = $this->getEmployeeData($employee->id, new \Documents\Common\Model\EmployeeDocument());
|
||||
}
|
||||
@@ -131,12 +137,14 @@ class EmployeesActionManager extends SubActionManager
|
||||
|
||||
$ok = $archived->Save();
|
||||
if (!$ok) {
|
||||
LogManager::getInstance()->error('Error occurred while archiving employee :'.$archived->ErrorMsg());
|
||||
return new IceResponse(IceResponse::ERROR, "Error occurred while archiving employee");
|
||||
}
|
||||
|
||||
|
||||
$ok = $employee->Delete();
|
||||
if (!$ok) {
|
||||
LogManager::getInstance()->error('Error occurred while deleting employee :'.$employee->ErrorMsg());
|
||||
return new IceResponse(IceResponse::ERROR, "Error occurred while deleting employee");
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace Employees\Admin\Api;
|
||||
|
||||
use Classes\AbstractModuleManager;
|
||||
use Classes\Macaw;
|
||||
use Classes\UIManager;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Employees\Rest\EmployeeRestEndPoint;
|
||||
@@ -26,32 +27,32 @@ class EmployeesAdminManager extends AbstractModuleManager
|
||||
|
||||
public function setupRestEndPoints()
|
||||
{
|
||||
\Classes\Macaw::get(REST_API_PATH.'employees/me', function () {
|
||||
Macaw::get(REST_API_PATH.'employees/me', function () {
|
||||
$empRestEndPoint = new EmployeeRestEndPoint();
|
||||
$empRestEndPoint->process('get', 'me');
|
||||
});
|
||||
|
||||
\Classes\Macaw::get(REST_API_PATH.'employees/(:num)', function ($pathParams) {
|
||||
Macaw::get(REST_API_PATH.'employees/(:num)', function ($pathParams) {
|
||||
$empRestEndPoint = new EmployeeRestEndPoint();
|
||||
$empRestEndPoint->process('get', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::get(REST_API_PATH.'employees', function () {
|
||||
Macaw::get(REST_API_PATH.'employees', function () {
|
||||
$empRestEndPoint = new EmployeeRestEndPoint();
|
||||
$empRestEndPoint->process('listAll');
|
||||
});
|
||||
|
||||
\Classes\Macaw::post(REST_API_PATH.'employees', function () {
|
||||
Macaw::post(REST_API_PATH.'employees', function () {
|
||||
$empRestEndPoint = new EmployeeRestEndPoint();
|
||||
$empRestEndPoint->process('post');
|
||||
});
|
||||
|
||||
\Classes\Macaw::put(REST_API_PATH.'employees/(:num)', function ($pathParams) {
|
||||
Macaw::put(REST_API_PATH.'employees/(:num)', function ($pathParams) {
|
||||
$empRestEndPoint = new EmployeeRestEndPoint();
|
||||
$empRestEndPoint->process('put', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::delete(REST_API_PATH.'employees/(:num)', function ($pathParams) {
|
||||
Macaw::delete(REST_API_PATH.'employees/(:num)', function ($pathParams) {
|
||||
$empRestEndPoint = new EmployeeRestEndPoint();
|
||||
$empRestEndPoint->process('delete', $pathParams);
|
||||
});
|
||||
@@ -86,16 +87,26 @@ class EmployeesAdminManager extends AbstractModuleManager
|
||||
public function initQuickAccessMenu()
|
||||
{
|
||||
UIManager::getInstance()->addQuickAccessMenuItem(
|
||||
"View Employees",
|
||||
"fa-users",
|
||||
CLIENT_BASE_URL."?g=admin&n=employees&m=admin_Employees",
|
||||
array("Admin","Manager")
|
||||
'View Employees',
|
||||
'fa-users',
|
||||
CLIENT_BASE_URL.'?g=admin&n=employees&m=admin_Employees',
|
||||
array('Admin','Manager')
|
||||
);
|
||||
UIManager::getInstance()->addQuickAccessMenuItem(
|
||||
"Add a New Employee",
|
||||
"fa-edit",
|
||||
CLIENT_BASE_URL."?g=admin&n=employees&m=admin_Employees&action=new",
|
||||
array("Admin")
|
||||
'Add a New Employee',
|
||||
'fa-edit',
|
||||
CLIENT_BASE_URL.'?g=admin&n=employees&m=admin_Employees&action=new',
|
||||
array('Admin')
|
||||
);
|
||||
}
|
||||
|
||||
public function initCalculationHooks()
|
||||
{
|
||||
$this->addCalculationHook(
|
||||
'EmployeeData_getFieldValue',
|
||||
'Get Employee Data',
|
||||
EmployeeUtil::class,
|
||||
'getEmployeeDataField'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Employees\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class ArchivedEmployee extends BaseModel
|
||||
@@ -31,5 +32,12 @@ class ArchivedEmployee extends BaseModel
|
||||
return "id";
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
];
|
||||
}
|
||||
|
||||
public $table = 'ArchivedEmployees';
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Employees\Common\Model;
|
||||
use Classes\BaseService;
|
||||
use Classes\FileService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Company\Common\Model\CompanyStructure;
|
||||
use Metadata\Common\Model\Country;
|
||||
use Model\BaseModel;
|
||||
@@ -235,5 +236,13 @@ class Employee extends BaseModel
|
||||
return $country->id;
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('employees', 'user'),
|
||||
];
|
||||
}
|
||||
|
||||
public $table = 'Employees';
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Employees\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class EmployeeApproval extends BaseModel
|
||||
@@ -29,4 +30,12 @@ class EmployeeApproval extends BaseModel
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('employees', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Employees\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class EmploymentStatus extends BaseModel
|
||||
@@ -24,4 +25,12 @@ class EmploymentStatus extends BaseModel
|
||||
{
|
||||
return array("get","element","save");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
new ModuleAccess('employees', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,35 @@ class EmployeeRestEndPoint extends RestEndPoint
|
||||
{
|
||||
$query = new DataQuery('Employee');
|
||||
|
||||
$mapping = <<<JSON
|
||||
{
|
||||
"job_title": [ "JobTitle", "id", "name" ],
|
||||
"country": [ "Country", "code", "name" ],
|
||||
"province": [ "Province", "id", "name" ],
|
||||
"department": [ "CompanyStructure", "id", "title" ],
|
||||
"supervisor": [ "Employee", "id", "first_name+last_name" ]
|
||||
}
|
||||
JSON;
|
||||
$query->setFieldMapping($mapping);
|
||||
|
||||
$limit = self::DEFAULT_LIMIT;
|
||||
if (isset($_GET['limit']) && intval($_GET['limit']) > 0) {
|
||||
$limit = intval($_GET['limit']);
|
||||
}
|
||||
$query->setLength($limit);
|
||||
|
||||
if (!empty($_GET['filters'])) {
|
||||
$query->setFilters($_GET['filters']);
|
||||
}
|
||||
|
||||
if (isset($_GET['sortField']) && !empty($_GET['sortField'])) {
|
||||
$query->setSortColumn($_GET['sortField']);
|
||||
$query->setSortingEnabled(true);
|
||||
$query->setSortOrder(
|
||||
empty($_GET['sortOrder']) || $_GET['sortOrder'] === 'ascend' ? 'ASC' : 'DESC'
|
||||
);
|
||||
}
|
||||
|
||||
if ($user->user_level !== 'Admin') {
|
||||
$query->setIsSubOrdinates(true);
|
||||
}
|
||||
@@ -55,27 +78,36 @@ class EmployeeRestEndPoint extends RestEndPoint
|
||||
return new IceResponse(IceResponse::ERROR, "Permission denied", 403);
|
||||
}
|
||||
|
||||
$mapping = [
|
||||
"nationality" => ["Nationality","id","name"],
|
||||
"ethnicity" => ["Ethnicity","id","name"],
|
||||
"immigration_status" => ["ImmigrationStatus","id","name"],
|
||||
"employment_status" => ["EmploymentStatus","id","name"],
|
||||
"job_title" => ["JobTitle","id","name"],
|
||||
"pay_grade" => ["PayGrade","id","name"],
|
||||
"country" => ["Country","code","name"],
|
||||
"province" => ["Province","id","name"],
|
||||
"department" => ["CompanyStructure","id","title"],
|
||||
"supervisor" => [self::ELEMENT_NAME,"id","first_name+last_name"],
|
||||
];
|
||||
// https://csvjson.com/json_beautifier
|
||||
|
||||
|
||||
$mapping = <<<JSON
|
||||
{
|
||||
"nationality": [ "Nationality", "id", "name" ],
|
||||
"ethnicity": [ "Ethnicity", "id", "name" ],
|
||||
"immigration_status": [ "ImmigrationStatus", "id", "name" ],
|
||||
"employment_status": [ "EmploymentStatus", "id", "name" ],
|
||||
"job_title": [ "JobTitle", "id", "name" ],
|
||||
"pay_grade": [ "PayGrade", "id", "name" ],
|
||||
"country": [ "Country", "code", "name" ],
|
||||
"province": [ "Province", "id", "name" ],
|
||||
"department": [ "CompanyStructure", "id", "title" ],
|
||||
"supervisor": [ "Employee", "id", "first_name+last_name" ],
|
||||
"indirect_supervisors": [ "Employee", "id", "first_name+last_name" ],
|
||||
"approver1": [ "Employee", "id", "first_name+last_name" ],
|
||||
"approver2": [ "Employee", "id", "first_name+last_name" ],
|
||||
"approver3": [ "Employee", "id", "first_name+last_name" ]
|
||||
}
|
||||
JSON;
|
||||
|
||||
$emp = BaseService::getInstance()->getElement(
|
||||
self::ELEMENT_NAME,
|
||||
$parameter,
|
||||
json_encode($mapping),
|
||||
null,
|
||||
true
|
||||
);
|
||||
|
||||
$emp = $this->enrichElement($emp, $mapping);
|
||||
$emp = $this->enrichElement($emp, json_decode($mapping, true));
|
||||
//Get User for the employee
|
||||
$user = new User();
|
||||
$user->Load('employee = ?', [$emp->id]);
|
||||
|
||||
@@ -11,11 +11,13 @@ namespace Employees\User\Api;
|
||||
use Classes\BaseService;
|
||||
use Classes\FileService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\PasswordManager;
|
||||
use Classes\SettingsManager;
|
||||
use Classes\SubActionManager;
|
||||
use Company\Common\Model\CompanyStructure;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Users\Common\Model\User;
|
||||
use Utils\LogManager;
|
||||
|
||||
class EmployeesActionManager extends SubActionManager
|
||||
{
|
||||
@@ -104,6 +106,7 @@ class EmployeesActionManager extends SubActionManager
|
||||
try {
|
||||
$employee = BaseService::getInstance()->customFieldManager->enrichObjectCustomFields('Employee', $employee);
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
}
|
||||
|
||||
if (empty($employee->id)) {
|
||||
@@ -143,11 +146,18 @@ class EmployeesActionManager extends SubActionManager
|
||||
if (empty($user->id)) {
|
||||
return new IceResponse(IceResponse::ERROR, "Error occurred while changing password");
|
||||
}
|
||||
$user->password = md5($req->pwd);
|
||||
|
||||
$passwordStrengthResponse = PasswordManager::isQualifiedPassword($req->pwd);
|
||||
if ($passwordStrengthResponse->getStatus() === IceResponse::ERROR) {
|
||||
return $passwordStrengthResponse;
|
||||
}
|
||||
|
||||
$user->password = PasswordManager::createPasswordHash($req->pwd);
|
||||
$ok = $user->Save();
|
||||
if (!$ok) {
|
||||
return new IceResponse(IceResponse::ERROR, $user->ErrorMsg());
|
||||
}
|
||||
|
||||
return new IceResponse(IceResponse::SUCCESS, $user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace FieldNames\Common\Model;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class CustomField extends BaseModel
|
||||
@@ -56,4 +57,11 @@ class CustomField extends BaseModel
|
||||
|
||||
return new IceResponse(IceResponse::SUCCESS, "");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('fieldnames', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace FieldNames\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class FieldNameMapping extends BaseModel
|
||||
@@ -23,4 +24,11 @@ class FieldNameMapping extends BaseModel
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('fieldnames', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Jobs\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class JobTitle extends BaseModel
|
||||
@@ -18,4 +19,11 @@ class JobTitle extends BaseModel
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Jobs\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class PayGrade extends BaseModel
|
||||
@@ -18,4 +19,11 @@ class PayGrade extends BaseModel
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('employees', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Loans\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class CompanyLoan extends BaseModel
|
||||
@@ -18,4 +19,11 @@ class CompanyLoan extends BaseModel
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('loans', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Loans\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class EmployeeCompanyLoan extends BaseModel
|
||||
@@ -33,4 +34,12 @@ class EmployeeCompanyLoan extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('loans', 'admin'),
|
||||
new ModuleAccess('loans', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace Metadata\Common\Model;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class CalculationHook extends BaseModel
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Metadata\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Classes\SettingsManager;
|
||||
use Model\BaseModel;
|
||||
|
||||
@@ -46,4 +47,11 @@ class Country extends BaseModel
|
||||
return parent::Find($whereOrderBy, $bindarr, $pkeysArr, $extra);
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('metadata', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Metadata\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Classes\SettingsManager;
|
||||
use Model\BaseModel;
|
||||
|
||||
@@ -46,4 +47,11 @@ class CurrencyType extends BaseModel
|
||||
return parent::Find($whereOrderBy, $bindarr, $pkeysArr, $extra);
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('metadata', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Metadata\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class Ethnicity extends BaseModel
|
||||
@@ -28,4 +29,11 @@ class Ethnicity extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('metadata', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Metadata\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class ImmigrationStatus extends BaseModel
|
||||
@@ -28,4 +29,11 @@ class ImmigrationStatus extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('metadata', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Metadata\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Classes\SettingsManager;
|
||||
use Model\BaseModel;
|
||||
|
||||
@@ -45,4 +46,11 @@ class Nationality extends BaseModel
|
||||
return parent::Find($whereOrderBy, $bindarr, $pkeysArr, $extra);
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('metadata', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Metadata\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class Province extends BaseModel
|
||||
@@ -23,4 +24,11 @@ class Province extends BaseModel
|
||||
{
|
||||
return array("get", "element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('metadata', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Metadata\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class SupportedLanguage extends BaseModel
|
||||
@@ -28,4 +29,11 @@ class SupportedLanguage extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('metadata', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@ abstract class ApproveModel extends BaseModel
|
||||
|
||||
if ($user->user_level == "Admin") {
|
||||
//Auto approve
|
||||
$obj->status = "Approved";
|
||||
$notificationMsg = "Your ".$this->notificationUnitName
|
||||
." is auto approved since you are an administrator and do not have any supervisor assigned";
|
||||
$obj->status = 'Approved';
|
||||
$notificationMsg = 'Your '.$this->notificationUnitName
|
||||
.' is auto approved since you are an administrator and do not have any supervisor assigned';
|
||||
BaseService::getInstance()->notificationManager->addNotification(
|
||||
null,
|
||||
$notificationMsg,
|
||||
@@ -76,11 +76,11 @@ abstract class ApproveModel extends BaseModel
|
||||
//If the user do not have a supervisor, notify all admins
|
||||
$admins = BaseService::getInstance()->getAllAdmins();
|
||||
foreach ($admins as $admin) {
|
||||
$notificationMsg = "A new ".$this->notificationUnitName." has been added by "
|
||||
.$employee->first_name . " " . $employee->last_name . ". Please visit "
|
||||
$notificationMsg = 'A new '.$this->notificationUnitName.' has been added by '
|
||||
.$employee->first_name . ' ' . $employee->last_name . '. Please visit '
|
||||
.$this->notificationModuleName
|
||||
." module to review it. You are getting this notification since you are an "
|
||||
."administrator and the user do not have any supervisor assigned.";
|
||||
.' module to review it. You are getting this notification since you are an '
|
||||
.'administrator and the user do not have any supervisor assigned.';
|
||||
BaseService::getInstance()->notificationManager->addNotification(
|
||||
null,
|
||||
$notificationMsg,
|
||||
@@ -151,22 +151,22 @@ abstract class ApproveModel extends BaseModel
|
||||
} else {
|
||||
$user = BaseService::getInstance()->getCurrentUser();
|
||||
|
||||
if ($user->user_level == "Admin") {
|
||||
if ($user->user_level == 'Admin') {
|
||||
} else {
|
||||
//If the user do not have a supervisor, notify all admins
|
||||
$admins = BaseService::getInstance()->getAllAdmins();
|
||||
foreach ($admins as $admin) {
|
||||
$notificationMsg = $this->notificationUnitPrefix." "
|
||||
.$this->notificationUnitName." request has been updated by "
|
||||
.$employee->first_name . " " . $employee->last_name
|
||||
.". Please visit ".$this->notificationModuleName
|
||||
." module to review it. You are getting this notification since you are "
|
||||
."an administrator and the user do not have any supervisor assigned.";
|
||||
$notificationMsg = $this->notificationUnitPrefix.' '
|
||||
.$this->notificationUnitName.' request has been updated by '
|
||||
.$employee->first_name . ' ' . $employee->last_name
|
||||
.'. Please visit '.$this->notificationModuleName
|
||||
.' module to review it. You are getting this notification since you are '
|
||||
.'an administrator and the user do not have any supervisor assigned.';
|
||||
BaseService::getInstance()->notificationManager->addNotification(
|
||||
null,
|
||||
$notificationMsg,
|
||||
'{"type":"url","url":"g=admin&n=travel&m=admin_Employees"}',
|
||||
"Travel Module",
|
||||
'Travel Module',
|
||||
$admin->id,
|
||||
false,
|
||||
$sendNotificationEmail
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
|
||||
class Audit extends BaseModel
|
||||
{
|
||||
public $table = 'AuditLog';
|
||||
@@ -21,4 +23,11 @@ class Audit extends BaseModel
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('audit', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<?php
|
||||
namespace Model;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Classes\ModuleAccessService;
|
||||
use Modules\Common\Model\Module;
|
||||
use Utils\LogManager;
|
||||
|
||||
class BaseModel extends \ADOdb_Active_Record
|
||||
{
|
||||
@@ -24,9 +29,62 @@ class BaseModel extends \ADOdb_Active_Record
|
||||
return array("get","element","save","delete");
|
||||
}
|
||||
|
||||
public function getOtherAccess()
|
||||
private function getRestrictedAccess($userRoles, $allowedAccessMatrix)
|
||||
{
|
||||
return array();
|
||||
if (empty($userRoles)) {
|
||||
return $this->getDefaultAccessLevel();
|
||||
}
|
||||
|
||||
$userRoles = json_decode($userRoles, true);
|
||||
|
||||
if (empty($userRoles)) {
|
||||
return $this->getDefaultAccessLevel();
|
||||
}
|
||||
|
||||
$moduleAccessData = $this->getModuleAccess();
|
||||
if (empty($moduleAccessData)) {
|
||||
return $this->getDefaultAccessLevel();
|
||||
}
|
||||
|
||||
$modules = [];
|
||||
/** @var ModuleAccess $moduleAccess */
|
||||
foreach ($moduleAccessData as $moduleAccess) {
|
||||
$modules[] = ModuleAccessService::getInstance()->getModule(
|
||||
$moduleAccess->getName(),
|
||||
$moduleAccess->getGroup()
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($modules)) {
|
||||
return $this->getDefaultAccessLevel();
|
||||
}
|
||||
|
||||
foreach ($modules as $module) {
|
||||
if (empty($module->user_roles) || $module->user_roles == '[]') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count(array_intersect($userRoles, json_decode($module->user_roles, true))) > 0) {
|
||||
return $allowedAccessMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->getDefaultAccessLevel();
|
||||
}
|
||||
|
||||
public function getRestrictedAdminAccess($userRoles)
|
||||
{
|
||||
return $this->getRestrictedAccess($userRoles, $this->getAdminAccess());
|
||||
}
|
||||
|
||||
public function getRestrictedManagerAccess($userRoles)
|
||||
{
|
||||
return $this->getRestrictedAccess($userRoles, $this->getAdminAccess());
|
||||
}
|
||||
|
||||
public function getRestrictedEmployeeAccess($userRoles)
|
||||
{
|
||||
return $this->getRestrictedAccess($userRoles, $this->getAdminAccess());
|
||||
}
|
||||
|
||||
public function getManagerAccess()
|
||||
@@ -69,6 +127,11 @@ class BaseModel extends \ADOdb_Active_Record
|
||||
return "employee";
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function validateSave($obj)
|
||||
{
|
||||
return new IceResponse(IceResponse::SUCCESS, "");
|
||||
@@ -109,7 +172,7 @@ class BaseModel extends \ADOdb_Active_Record
|
||||
|
||||
public function getDefaultAccessLevel()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
return $this->getAnonymousAccess();
|
||||
}
|
||||
|
||||
public function getVirtualFields()
|
||||
@@ -125,7 +188,7 @@ class BaseModel extends \ADOdb_Active_Record
|
||||
|
||||
public function getDisplayName()
|
||||
{
|
||||
return get_called_class();
|
||||
return $this->getEntity();
|
||||
}
|
||||
|
||||
public function fieldValueMethods()
|
||||
@@ -179,4 +242,67 @@ class BaseModel extends \ADOdb_Active_Record
|
||||
|
||||
return $keys;
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
|
||||
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
|
||||
{
|
||||
if ($cache && BaseService::getInstance()->queryCacheEnabled()) {
|
||||
$data = BaseService::getInstance()->getCacheService()->getDBQuery($this->getEntity(),$whereOrderBy, $bindarr);
|
||||
if ($data !== null) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
$data = parent::Find($whereOrderBy, $bindarr, $pkeysArr, $extra);
|
||||
|
||||
if (empty($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($cache && BaseService::getInstance()->queryCacheEnabled()) {
|
||||
BaseService::getInstance()->getCacheService()->setDBQuery($this->getEntity(),$whereOrderBy, $bindarr, $data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getEntity()
|
||||
{
|
||||
$data = explode('\\', get_called_class());
|
||||
return end($data);
|
||||
}
|
||||
|
||||
public function Save()
|
||||
{
|
||||
$ok = parent::Save();
|
||||
if (!$ok) {
|
||||
$message = sprintf('%s: (%s) %s', 'Error saving :', $this->ErrorMsg(), json_encode($this));
|
||||
LogManager::getInstance()->error($message);
|
||||
LogManager::getInstance()->notifyException(new \Exception($message));
|
||||
}
|
||||
if (BaseService::getInstance()->queryCacheEnabled()) {
|
||||
BaseService::getInstance()->getCacheService()->deleteByEntity($this->getEntity());
|
||||
}
|
||||
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
public function Delete()
|
||||
{
|
||||
$ok = parent::Delete();
|
||||
if (!$ok) {
|
||||
$message = sprintf('%s: (%s) %s', 'Error deleting', $this->ErrorMsg(), json_encode($this));
|
||||
LogManager::getInstance()->error($message);
|
||||
LogManager::getInstance()->notifyException(new \Exception($message));
|
||||
}
|
||||
|
||||
if (BaseService::getInstance()->queryCacheEnabled()) {
|
||||
BaseService::getInstance()->getCacheService()->deleteByEntity($this->getEntity());
|
||||
}
|
||||
|
||||
return $ok;
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
|
||||
8
core/src/Model/EmailLogEntry.php
Normal file
8
core/src/Model/EmailLogEntry.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Model;
|
||||
|
||||
class EmailLogEntry extends BaseModel
|
||||
{
|
||||
public $table = 'EmailLog';
|
||||
}
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
|
||||
class Report extends BaseModel
|
||||
{
|
||||
public function getAdminAccess()
|
||||
@@ -25,6 +27,13 @@ class Report extends BaseModel
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('reports', 'admin'),
|
||||
];
|
||||
}
|
||||
|
||||
public function postProcessGetData($entry)
|
||||
{
|
||||
$entry->icon = '<img src="'.BASE_URL.'images/file-icons/'.strtolower($entry->output).".png".'"/>';
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
|
||||
class ReportFile extends BaseModel
|
||||
{
|
||||
public function getAdminAccess()
|
||||
@@ -30,6 +32,13 @@ class ReportFile extends BaseModel
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('report_files', 'admin'),
|
||||
];
|
||||
}
|
||||
|
||||
public function postProcessGetData($entry)
|
||||
{
|
||||
$data = explode(".", $entry->name);
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Model;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Classes\RestApiManager;
|
||||
use Users\Common\Model\User;
|
||||
|
||||
@@ -30,6 +31,13 @@ class Setting extends BaseModel
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('settings', 'admin'),
|
||||
];
|
||||
}
|
||||
|
||||
public function postProcessGetElement($obj)
|
||||
{
|
||||
if ($obj->name == 'Api: REST Api Token') {
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
|
||||
class UserReport extends BaseModel
|
||||
{
|
||||
public function getAdminAccess()
|
||||
@@ -25,6 +27,13 @@ class UserReport extends BaseModel
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('reports', 'user'),
|
||||
];
|
||||
}
|
||||
|
||||
public function postProcessGetData($entry)
|
||||
{
|
||||
$entry->icon = '<img src="'.BASE_URL.'images/file-icons/'.strtolower($entry->output).".png".'"/>';
|
||||
|
||||
@@ -31,10 +31,10 @@ class ModulesAdminManager extends AbstractModuleManager
|
||||
public function initQuickAccessMenu()
|
||||
{
|
||||
UIManager::getInstance()->addQuickAccessMenuItem(
|
||||
"Setup Modules",
|
||||
"fa-cogs",
|
||||
CLIENT_BASE_URL."?g=admin&n=modules&m=admin_System",
|
||||
array("Admin")
|
||||
'Setup Modules',
|
||||
'fa-cogs',
|
||||
CLIENT_BASE_URL.'?g=admin&n=modules&m=admin_System',
|
||||
array('Admin')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,14 @@
|
||||
|
||||
namespace Modules\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Classes\ModuleAccessService;
|
||||
use Model\BaseModel;
|
||||
|
||||
class Module extends BaseModel
|
||||
{
|
||||
public $table = 'Modules';
|
||||
|
||||
public function getAdminAccess()
|
||||
{
|
||||
return array("get","element","save","delete");
|
||||
@@ -19,5 +23,28 @@ class Module extends BaseModel
|
||||
{
|
||||
return array();
|
||||
}
|
||||
public $table = 'Modules';
|
||||
|
||||
public function getUserModules()
|
||||
{
|
||||
$moduleList = [];
|
||||
$modules = ModuleAccessService::getInstance()->getModules();
|
||||
foreach ($modules as $md) {
|
||||
$md->name = sprintf('[%s] %s => %s', $md->mod_group, $md->menu, $md->label);
|
||||
$moduleList[] = $md;
|
||||
}
|
||||
|
||||
return $moduleList;
|
||||
}
|
||||
|
||||
public function fieldValueMethods()
|
||||
{
|
||||
return ['getUserModules'];
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('modules', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace Overtime\Common\Model;
|
||||
|
||||
use Classes\IceResponse;
|
||||
use Classes\ModuleAccess;
|
||||
use Classes\SettingsManager;
|
||||
use Model\ApproveModel;
|
||||
|
||||
@@ -75,4 +76,12 @@ class EmployeeOvertime extends ApproveModel
|
||||
}
|
||||
return new IceResponse(IceResponse::SUCCESS, "");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('overtime', 'admin'),
|
||||
new ModuleAccess('overtime', 'user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Overtime\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class OvertimeCategory extends BaseModel
|
||||
@@ -28,4 +29,11 @@ class OvertimeCategory extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('overtime', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ use Classes\SubActionManager;
|
||||
use Company\Common\Model\CompanyStructure;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Payroll\Common\Model\Deduction;
|
||||
use Payroll\Common\Model\DeductionGroup;
|
||||
use Payroll\Common\Model\Payroll;
|
||||
use Payroll\Common\Model\PayrollCalculations;
|
||||
use Payroll\Common\Model\PayrollColumn;
|
||||
@@ -23,6 +24,8 @@ use Salary\Common\Model\PayrollEmployee;
|
||||
use Salary\Common\Model\SalaryComponent;
|
||||
use Utils\LogManager;
|
||||
use Utils\Math\EvalMath;
|
||||
use Utils\ScriptRunner;
|
||||
use Classes\Migration\AbstractMigration;
|
||||
|
||||
class PayrollActionManager extends SubActionManager
|
||||
{
|
||||
@@ -52,19 +55,24 @@ class PayrollActionManager extends SubActionManager
|
||||
$payrollEmployeeId,
|
||||
$noColumnCalculations = false
|
||||
) {
|
||||
|
||||
|
||||
$val = $this->getFromCalculationCache($col->id."-".$payroll->id."-".$employeeId);
|
||||
if (!empty($val)) {
|
||||
return $val;
|
||||
}
|
||||
|
||||
if (!empty($col->calculation_hook)) {
|
||||
$sum = BaseService::getInstance()->executeCalculationHook(
|
||||
$valueData = BaseService::getInstance()->executeCalculationHook(
|
||||
array($employeeId, $payroll->date_start, $payroll->date_end),
|
||||
$col->calculation_hook,
|
||||
$col->calculation_function
|
||||
);
|
||||
$val = number_format(round($sum, 2), 2, '.', '');
|
||||
if (is_array($valueData) && $valueData[0] == 'string') {
|
||||
$val = $valueData[1];
|
||||
} else {
|
||||
$val = number_format(round($valueData, 2), 2, '.', '');
|
||||
}
|
||||
|
||||
$this->addToCalculationCache($col->id."-".$payroll->id."-".$employeeId, $val);
|
||||
return $val;
|
||||
}
|
||||
@@ -118,8 +126,10 @@ class PayrollActionManager extends SubActionManager
|
||||
|
||||
if (!$noColumnCalculations) {
|
||||
$evalMath = new EvalMath();
|
||||
$evalMath->evaluate('max(x,y) = (y - x) * ceil(tanh(exp(tanh(y - x)) - exp(0))) + x');
|
||||
$evalMath->evaluate('min(x,y) = y - (y - x) * ceil(tanh(exp(tanh(y - x)) - exp(0)))');
|
||||
if ($col->function_type === 'Simple') {
|
||||
$evalMath->evaluate('max(x,y) = (y - x) * ceil(tanh(exp(tanh(y - x)) - exp(0))) + x');
|
||||
$evalMath->evaluate('min(x,y) = y - (y - x) * ceil(tanh(exp(tanh(y - x)) - exp(0)))');
|
||||
}
|
||||
|
||||
if (!empty($col->add_columns) &&
|
||||
!empty(json_decode($col->add_columns, true))) {
|
||||
@@ -157,17 +167,27 @@ class PayrollActionManager extends SubActionManager
|
||||
!empty(json_decode($col->calculation_columns, true)) && !empty($col->calculation_function)) {
|
||||
$cc = json_decode($col->calculation_columns);
|
||||
$func = $col->calculation_function;
|
||||
$variableList = [];
|
||||
foreach ($cc as $c) {
|
||||
$value = $this->getFromCalculationCache($c->column."-".$payroll->id."-".$employeeId);
|
||||
if (empty($value)) {
|
||||
$value = 0.00;
|
||||
if ($col->function_type === 'Simple') {
|
||||
if (empty($value)) {
|
||||
$value = 0.00;
|
||||
}
|
||||
$func = str_replace($c->name, $value, $func);
|
||||
} else {
|
||||
$variableList[$c->name] = $value;
|
||||
}
|
||||
$func = str_replace($c->name, $value, $func);
|
||||
}
|
||||
try {
|
||||
$sum += $evalMath->evaluate($func);
|
||||
if ($col->function_type === 'Simple') {
|
||||
$sum += $evalMath->evaluate($func);
|
||||
} else {
|
||||
$sum = ScriptRunner::executeJs($variableList, $func);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
LogManager::getInstance()->info("Error:".$e->getMessage());
|
||||
LogManager::getInstance()->error("Error:".$e->getMessage());
|
||||
LogManager::getInstance()->notifyException($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -495,4 +515,62 @@ class PayrollActionManager extends SubActionManager
|
||||
|
||||
return new IceResponse(IceResponse::SUCCESS, true);
|
||||
}
|
||||
|
||||
public function deletePayrollGroup($req)
|
||||
{
|
||||
$employee = new PayrollEmployee();
|
||||
$report = new Payroll();
|
||||
$payrollGroup = new DeductionGroup();
|
||||
$payrollColumn = new PayrollColumn();
|
||||
$calcMethod =new Deduction();
|
||||
|
||||
|
||||
$payrollGroup->Load("id = ?", array($req->id));
|
||||
if (empty($payrollGroup->id)) {
|
||||
return new IceResponse(IceResponse::ERROR);
|
||||
}
|
||||
|
||||
$this->baseService->checkSecureAccess('delete', $payrollGroup, 'DeductionGroup', $_POST);
|
||||
$this->baseService->checkSecureAccess('delete', $payrollColumn, 'payrollColumn', $_POST);
|
||||
$this->baseService->checkSecureAccess('delete', $calcMethod, 'Deduction', $_POST);
|
||||
|
||||
$employee->Load("deduction_group = ?", $payrollGroup->id);
|
||||
$report->Load("deduction_group = ?", $payrollGroup->id);
|
||||
$payrollColumn->Load("deduction_group = ?", $payrollGroup->id);
|
||||
$calcMethod->Load("deduction_group = ?", $payrollGroup->id);
|
||||
|
||||
if (!empty($employee->id)) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
"There are employees attached to this payroll group,
|
||||
please re-assign employees to a different payroll group"
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($report->id)) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
"There are payroll reports attached to this group,
|
||||
please move the payroll reports to a different payroll group before deleting this group"
|
||||
);
|
||||
}
|
||||
|
||||
BaseService::getInstance()->getDB()->Execute(
|
||||
'DELETE FROM PayrollColumns WHERE deduction_group= ? ',
|
||||
array($req->id)
|
||||
);
|
||||
BaseService::getInstance()->getDB()->Execute(
|
||||
'DELETE FROM Deductions WHERE deduction_group= ? ',
|
||||
array($req->id)
|
||||
);
|
||||
$ok = $payrollGroup->Delete();
|
||||
if (!$ok) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
"Error occurred while deleting payroll group"
|
||||
);
|
||||
}
|
||||
|
||||
return new IceResponse(IceResponse::SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Payroll\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class Deduction extends BaseModel
|
||||
@@ -23,4 +24,11 @@ class Deduction extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('payroll', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Payroll\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class DeductionGroup extends BaseModel
|
||||
@@ -23,4 +24,11 @@ class DeductionGroup extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('payroll', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Payroll\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class PayFrequency extends BaseModel
|
||||
@@ -27,4 +28,11 @@ class PayFrequency extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('payroll', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace Payroll\Common\Model;
|
||||
|
||||
use Classes\BaseService;
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class Payroll extends BaseModel
|
||||
@@ -52,4 +53,11 @@ class Payroll extends BaseModel
|
||||
{
|
||||
return ['getEmployeePayrolls'];
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('payroll', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace Payroll\Common\Model;
|
||||
|
||||
use Attendance\Common\Model\Attendance;
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
use Salary\Common\Model\EmployeeSalary;
|
||||
use TimeSheets\Common\Model\EmployeeTimeSheet;
|
||||
@@ -119,4 +120,11 @@ class PayrollCalculations extends BaseModel
|
||||
|
||||
return round($hoursPartial, 2) . "(".round($hoursPartialUnapproved, 2).")";
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('payroll', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Payroll\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class PayrollColumn extends BaseModel
|
||||
@@ -27,4 +28,11 @@ class PayrollColumn extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('payroll', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Payroll\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class PayrollColumnTemplate extends BaseModel
|
||||
@@ -27,4 +28,11 @@ class PayrollColumnTemplate extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('payroll', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Payroll\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class PayrollData extends BaseModel
|
||||
@@ -28,4 +29,11 @@ class PayrollData extends BaseModel
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('payroll', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Payroll\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class PayslipTemplate extends BaseModel
|
||||
@@ -23,4 +24,11 @@ class PayslipTemplate extends BaseModel
|
||||
{
|
||||
return array("get","element");
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('payroll', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Permissions\Common\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class Permission extends BaseModel
|
||||
@@ -23,4 +24,11 @@ class Permission extends BaseModel
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('permissions', 'admin'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user