diff --git a/core-ext/config.base.php b/core-ext/config.base.php index 4a420dac..79d79506 100644 --- a/core-ext/config.base.php +++ b/core-ext/config.base.php @@ -9,9 +9,9 @@ define('HOME_LINK_ADMIN', CLIENT_BASE_URL."?g=admin&n=dashboard&m=admin_Admin"); define('HOME_LINK_OTHERS', CLIENT_BASE_URL."?g=modules&n=dashboard&m=module_Personal_Information"); //Version -define('VERSION', '15.0.OS'); -define('CACHE_VALUE', '15.0.OS'); -define('VERSION_DATE', '07/02/2016'); +define('VERSION', '15.3.OS'); +define('CACHE_VALUE', '15.3.OS'); +define('VERSION_DATE', '12/03/2016'); if(!defined('CONTACT_EMAIL')){define('CONTACT_EMAIL','icehrm@gamonoid.com');} if(!defined('KEY_PREFIX')){define('KEY_PREFIX','IceHrm');} diff --git a/core-ext/db_upgrade/upgrade_v15.0.OS_to_v15.2.OS.sql b/core-ext/db_upgrade/upgrade_v15.0.OS_to_v15.2.OS.sql new file mode 100644 index 00000000..f1bc7db9 --- /dev/null +++ b/core-ext/db_upgrade/upgrade_v15.0.OS_to_v15.2.OS.sql @@ -0,0 +1,23 @@ +INSERT INTO `Settings` (`name`, `value`, `description`, `meta`) VALUES + ('System: Default Country', '0', 'Set the default Country','[ "value", {"label":"Country","type":"select2","remote-source":["Country","code","name"]}]'); + +INSERT INTO `Settings` (`name`, `value`, `description`, `meta`) VALUES + ('Attendance: Overtime Calculation Class', 'BasicOvertimeCalculator', 'Set the method used to calculate overtime','["value", {"label":"Value","type":"select","source":[["BasicOvertimeCalculator","BasicOvertimeCalculator"],["CaliforniaOvertimeCalculator","CaliforniaOvertimeCalculator"]]}]'); + +INSERT INTO `Settings` (`name`, `value`, `description`, `meta`) VALUES + ('Attendance: Overtime Start Hour', '8', 'Overtime calculation will start after an employee work this number of hours per day, 0 to indicate no overtime', ''), + ('Attendance: Double time Start Hour', '12', 'Double time calculation will start after an employee work this number of hours per day, 0 to indicate no double time', ''); + +INSERT INTO `Settings` (`name`, `value`, `description`, `meta`) VALUES + ('Attendance: Work Week Start Day', '0', 'Set the starting day of the work week','["value", {"label":"Value","type":"select","source":[["0","Sunday"],["1","Monday"],["2","Tuesday"],["3","Wednesday"],["4","Thursday"],["5","Friday"],["6","Saturday"]]}]'); + +INSERT INTO `Reports` (`name`, `details`, `parameters`, `query`, `paramOrder`, `type`,`report_group`) VALUES +('Overtime Report', 'This report list all employee attendance entries by employee with overtime calculations', '[\r\n[ "employee", {"label":"Employee","type":"select2multi","allow-null":true,"null-label":"All Employees","remote-source":["Employee","id","first_name+last_name"]}],\r\n[ "date_start", {"label":"Start Date","type":"date"}],\r\n[ "date_end", {"label":"End Date","type":"date"}]\r\n]', 'OvertimeReport', '["employee","date_start","date_end"]', 'Class','Time Management'); + +INSERT INTO `Reports` (`name`, `details`, `parameters`, `query`, `paramOrder`, `type`,`report_group`) VALUES +('Overtime Summary Report', 'This report list all employee attendance entries by employee with overtime calculation summary', '[\r\n[ "employee", {"label":"Employee","type":"select2multi","allow-null":true,"null-label":"All Employees","remote-source":["Employee","id","first_name+last_name"]}],\r\n[ "date_start", {"label":"Start Date","type":"date"}],\r\n[ "date_end", {"label":"End Date","type":"date"}]\r\n]', 'OvertimeSummaryReport', '["employee","date_start","date_end"]', 'Class','Time Management'); + +Alter table `Employees` modify column `joined_date` date default '0000-00-00'; +Alter table `Employees` modify column `confirmation_date` date default '0000-00-00'; +Alter table `Employees` modify column `termination_date` date default '0000-00-00'; +Alter table `Employees` modify column `birthday` date default '0000-00-00'; diff --git a/core-ext/scripts/icehrm_master_data.sql b/core-ext/scripts/icehrm_master_data.sql index 526c488e..77de1aa7 100644 --- a/core-ext/scripts/icehrm_master_data.sql +++ b/core-ext/scripts/icehrm_master_data.sql @@ -798,6 +798,25 @@ REPLACE INTO `Reports` (`name`, `details`, `parameters`, `query`, `paramOrder`, '["employee","date_start","date_end","status"]', 'Class'); +INSERT INTO `Reports` (`name`, `details`, `parameters`, `query`, `paramOrder`, `type`,`report_group`) VALUES + ('Overtime Report', 'This report list all employee attendance entries by employee with overtime calculations', '[\r\n[ "employee", {"label":"Employee","type":"select2multi","allow-null":true,"null-label":"All Employees","remote-source":["Employee","id","first_name+last_name"]}],\r\n[ "date_start", {"label":"Start Date","type":"date"}],\r\n[ "date_end", {"label":"End Date","type":"date"}]\r\n]', 'OvertimeReport', '["employee","date_start","date_end"]', 'Class','Time Management'); + +INSERT INTO `Reports` (`name`, `details`, `parameters`, `query`, `paramOrder`, `type`,`report_group`) VALUES + ('Overtime Summary Report', 'This report list all employee attendance entries by employee with overtime calculation summary', '[\r\n[ "employee", {"label":"Employee","type":"select2multi","allow-null":true,"null-label":"All Employees","remote-source":["Employee","id","first_name+last_name"]}],\r\n[ "date_start", {"label":"Start Date","type":"date"}],\r\n[ "date_end", {"label":"End Date","type":"date"}]\r\n]', 'OvertimeSummaryReport', '["employee","date_start","date_end"]', 'Class','Time Management'); + + +INSERT INTO `Settings` (`name`, `value`, `description`, `meta`) VALUES + ('Attendance: Overtime Calculation Class', 'BasicOvertimeCalculator', 'Set the method used to calculate overtime','["value", {"label":"Value","type":"select","source":[["BasicOvertimeCalculator","BasicOvertimeCalculator"],["CaliforniaOvertimeCalculator","CaliforniaOvertimeCalculator"]]}]'); + +INSERT INTO `Settings` (`name`, `value`, `description`, `meta`) VALUES + ('Attendance: Overtime Start Hour', '8', 'Overtime calculation will start after an employee work this number of hours per day, 0 to indicate no overtime', ''), + ('Attendance: Double time Start Hour', '12', 'Double time calculation will start after an employee work this number of hours per day, 0 to indicate no double time', ''); + +INSERT INTO `Settings` (`name`, `value`, `description`, `meta`) VALUES + ('Attendance: Work Week Start Day', '0', 'Set the starting day of the work week','["value", {"label":"Value","type":"select","source":[["0","Sunday"],["1","Monday"],["2","Tuesday"],["3","Wednesday"],["4","Thursday"],["5","Friday"],["6","Saturday"]]}]'); + + + INSERT INTO `Settings` (`name`, `value`, `description`, `meta`) VALUES ('Company: Logo', '', '','[ "value", {"label":"Logo","type":"fileupload","validation":"none"}]'), ('Company: Name', 'Sample Company Pvt Ltd', 'Update your company name - For updating company logo copy a file named logo.png to /app/data/ folder', ''), diff --git a/readme.md b/readme.md index 49bc45b2..7f72632e 100644 --- a/readme.md +++ b/readme.md @@ -532,6 +532,21 @@ That way you can attach each and every project to a client. Under employee projects tab you can assign projects to employees. You need to add projects to employees to enable them to add time against these projects in time-sheets. +Release note v15.2 +------------------ + +### Features + * Overtime Reports + * Overtime calculation for california + +### Fixes + * Fix issue: uncaught error when placeholder value is empty + * Log email sending success status + * Fix broken longer company name issue + * Make the application accessible when client on an intranet with no internet connection + * Fix issue: when a module is disabled other modules depend on it stops working + + Release note v15.0 ------------------ diff --git a/src/api/Base.js b/src/api/Base.js index 9628b9bd..2abfff35 100644 --- a/src/api/Base.js +++ b/src/api/Base.js @@ -1678,7 +1678,10 @@ IceHRMBase.method('fillForm', function(object, formId, fields) { if(placeHolderVal == undefined || placeHolderVal == null){ placeHolderVal = ""; }else{ - placeHolderVal = placeHolderVal.replace(/(?:\r\n|\r|\n)/g, '
'); + try{ + placeHolderVal = placeHolderVal.replace(/(?:\r\n|\r|\n)/g, '
'); + }catch(e){} + } @@ -2160,3 +2163,12 @@ IceHRMBase.method('generateOptions', function (data) { return options; }); + +IceHRMBase.method('isModuleInstalled', function (type, name) { + if(modulesInstalled == undefined || modulesInstalled == null){ + return false; + } + + return (modulesInstalled[type+"_"+name] == 1); +}); + diff --git a/src/classes/AbstractModuleManager.php b/src/classes/AbstractModuleManager.php index 3f7e3824..94191c92 100644 --- a/src/classes/AbstractModuleManager.php +++ b/src/classes/AbstractModuleManager.php @@ -194,5 +194,19 @@ abstract class AbstractModuleManager{ $this->modelClasses[] = $className; } + protected function addHistoryGeneric($type, $table, $refName, $refId, $field, $oldValue, $newValue){ + $eh = new $table(); + $eh->type = $type; + $eh->$refName = $refId; + $eh->field = $field; + $eh->user = BaseService::getInstance()->getCurrentUser()->id; + $eh->old_value = $oldValue; + $eh->new_value = $newValue; + $eh->created = date("Y-m-d H:i:s"); + $eh->updated = date("Y-m-d H:i:s"); + + $eh->Save(); + } + } \ No newline at end of file diff --git a/src/classes/BaseService.php b/src/classes/BaseService.php index 5e56cd7d..e56f2248 100644 --- a/src/classes/BaseService.php +++ b/src/classes/BaseService.php @@ -45,6 +45,7 @@ class BaseService{ var $moduleManagers = null; var $emailSender = null; var $user = null; + var $historyManagers = array(); private static $me = null; @@ -89,17 +90,23 @@ class BaseService{ $queryData = array(); if(!empty($filterStr)){ $filter = json_decode($filterStr, true); - - if(!empty($filter)){ - foreach($filter as $k=>$v){ - LogManager::getInstance()->info($filterStr); - if($v == '__myid__'){ - $v = $this->getCurrentProfileId(); - } - $query.=" and ".$k."=?"; - $queryData[] = $v; - } - } + + + 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]; + } + + } } if(empty($orderBy)){ @@ -112,13 +119,17 @@ class BaseService{ if(in_array($table, $this->userTables)){ $cemp = $this->getCurrentProfileId(); if(!empty($cemp)){ - $signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME; - $list = $obj->Find($signInMappingField." = ?".$query.$orderBy, array_merge(array($cemp),$queryData)); + $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(); } }else{ + LogManager::getInstance()->debug("Query: "."1=1".$query.$orderBy); + LogManager::getInstance()->debug("Query Data: ".print_r($queryData,true)); $list = $obj->Find("1=1".$query.$orderBy,$queryData); } @@ -136,19 +147,19 @@ class BaseService{ if(empty($v)){ continue; } - $vArr = json_decode($v); - if(is_array($vArr)){ - if(empty($vArr)){ + if(is_array($v)){ + if(empty($v)){ continue; } - $v = $vArr; $length = count($v); for($i=0; $i<$length; $i++){ - $query.=$k." like ?"; + if($i == 0){ $query.=" and ("; } + + $query.=$k." like ?"; if($i < $length -1){ $query.=" or "; @@ -477,7 +488,7 @@ class BaseService{ } } } - return $obj; + return $obj->postProcessGetData($obj); } return null; } @@ -1065,6 +1076,37 @@ class BaseService{ return true; + } + + public function isModuleAllowedForGivenUser($moduleManagerObj, $user){ + $moduleObject = $moduleManagerObj->getModuleObject(); + + //Check if the module is disabled + if($moduleObject['status'] == 'Disabled'){ + return false; + } + + //Check if user has permissions to this module + //Check Module Permissions + $modulePermissions = BaseService::getInstance()->loadModulePermissions($moduleManagerObj->getModuleType(), $moduleObject['name'],$user->user_level); + + + if(!in_array($user->user_level, $modulePermissions['user'])){ + + if(!empty($user->user_roles)){ + $userRoles = json_decode($user->user_roles,true); + }else{ + $userRoles = array(); + } + $commonRoles = array_intersect($modulePermissions['user_roles'], $userRoles); + if(empty($commonRoles)){ + return false; + } + + } + + return true; + } public function getGAKey(){ @@ -1123,12 +1165,27 @@ class BaseService{ if(empty($this->moduleManagers)){ $this->moduleManagers = array(); } - $this->moduleManagers[] = $moduleManager; + $moduleObject = $moduleManager->getModuleObject(); + $this->moduleManagers[$moduleManager->getModuleType()."_".$moduleObject['name']] = $moduleManager; } public function getModuleManagers(){ - return $this->moduleManagers; + return array_values($this->moduleManagers); } + + public function getModuleManagerNames(){ + $keys = array_keys($this->moduleManagers); + $arr = array(); + foreach($keys as $key){ + $arr[$key] = 1; + } + + return $arr; + } + + public function getModuleManager($type, $name){ + return $this->moduleManagers[$type."_".$name]; + } public function setEmailSender($emailSender){ $this->emailSender = $emailSender; @@ -1173,8 +1230,116 @@ class BaseService{ return $dept->timezone; } + + public function setupHistoryManager($type, $historyManager){ + $this->historyManagers[$type] = $historyManager; + } + + public function addHistoryItem($historyManagerType, $type, $refId , $field, $oldVal, $newVal){ + if(isset($this->historyManagers[$historyManagerType])){ + return $this->historyManagers[$historyManagerType]->addHistory($type, $refId , $field, $oldVal, $newVal); + } + return false; + } + + public function getItemFromCache($class, $id){ + $data = MemcacheService::getInstance()->get($class."-".$id); + if($data !== false){ + return unserialize($data); + } + + $obj = new $class(); + $obj->Load("id = ?",array($id)); + if($obj->id != $id){ + return null; + } + + MemcacheService::getInstance()->set($class."-".$id, serialize($obj), 10 * 60); + + return $obj; + + } } + +class MemcacheService { + + private $connection = null; + public static $openConnections = array(); + private static $me = null; + + private function __construct(){} + + public static function getInstance(){ + if(self::$me == null){ + self::$me = new MemcacheService(); + } + + return self::$me; + } + + + private function connect() { + + if($this->connection == null) { + $this->connection = new Memcached(); + $this->connection->addServer(MEMCACHE_HOST, MEMCACHE_PORT); + + if(!$this->isConnected()) { + $this->connection = null; + } else { + self::$openConnections[] = $this->connection; + } + } + return $this->connection; + } + + private function isConnected(){ + $statuses = $this->connection->getStats(); + return isset($statuses[$this->memcacheHost.":".$this->memcachePort]); + } + + private function compressKey($key) { + return crc32(APP_DB.$key).md5(CLIENT_NAME); + } + + public function set($key, $value, $expiry = 3600) { + $key = $this->compressKey($key); + $memcache = $this->connect(); + + if (!empty($memcache) && $this->isConnected()) { + $ok = $memcache->set($key, $value, time() + $expiry); + if(!$ok) { + return false; + } + return true; + } + return false; + } + + + public function get($key) { + $key = $this->compressKey($key); + $memcache = $this->connect(); + if(!empty($memcache) && $this->isConnected()) { + return $memcache->get($key); + } else { + return false; + } + } + + public function close() { + if($this->connection != null) { + if($this->isConnected()) { + $this->connection->quit(); + } + $this->connection = null; + } + } +} + + + class IceConstants{ const AUDIT_AUTHENTICATION = "Authentication"; const AUDIT_ADD = "Add"; @@ -1186,4 +1351,8 @@ class IceConstants{ const NOTIFICATION_LEAVE = "Leave Module"; const NOTIFICATION_TIMESHEET = "Time Module"; const NOTIFICATION_TRAINING = "Training Module"; +} + +interface HistoryManager{ + public function addHistory($type, $refId, $field, $oldValue, $newValue); } \ No newline at end of file diff --git a/src/classes/EmailSender.php b/src/classes/EmailSender.php index 72678dc8..3006acf0 100644 --- a/src/classes/EmailSender.php +++ b/src/classes/EmailSender.php @@ -40,7 +40,7 @@ abstract class EmailSender{ array(), array(), array() - ); + ); } } @@ -281,7 +281,9 @@ class SMTPEmailSender extends EmailSender{ $mail = $smtp->send($toEmail, $headers, $body); - + if (PEAR::isError($mail)) { + LogManager::getInstance()->info("SMTP Error Response:".$mail->getMessage()); + } return $mail; } diff --git a/src/classes/FileService.php b/src/classes/FileService.php index a5da64e9..2ce63c1f 100644 --- a/src/classes/FileService.php +++ b/src/classes/FileService.php @@ -41,17 +41,22 @@ class FileService{ public function getFromCache($key){ try{ + /* if(empty($this->memcache)){ $this->memcache = new Memcached(); $this->memcache->addServer("127.0.0.1", 11211); } - $data = $this->memcache->get($key); + */ + + $data = MemcacheService::getInstance()->get($key); + if(!empty($data)){ return $data; } return null; + }catch(Exception $e){ return null; } diff --git a/src/css/style.css b/src/css/style.css index 87eedef3..748975df 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -651,4 +651,14 @@ table.dataTable{ border-radius: 0px; -moz-border-radius: 0px; -webkit-border-radius: 0px; +} + +.logoResponsive{ + background: #3c8dbc !important; + text-align: left !important; + width:50% !important; +} + +@media screen and (min-width: 0px) and (max-width: 600px) { + .logoResponsive { display: none !important;} } \ No newline at end of file diff --git a/src/fileupload_page.php b/src/fileupload_page.php index e57ce0de..546c7c7c 100644 --- a/src/fileupload_page.php +++ b/src/fileupload_page.php @@ -14,9 +14,9 @@ if($_REQUEST['file_type']=="image"){ ?> - - - + + + diff --git a/src/footer.php b/src/footer.php index 173f2f51..dfaa152e 100644 --- a/src/footer.php +++ b/src/footer.php @@ -105,6 +105,8 @@ }); var clientUrl = ''; + var modulesInstalled = getModuleManagerNames())?>; + $(document).ready(function() { $(".dataTables_paginate ul").addClass("pagination"); diff --git a/src/header.php b/src/header.php index 5a386bff..008d0c6a 100644 --- a/src/header.php +++ b/src/header.php @@ -58,8 +58,12 @@ if(!in_array($user->user_level, $modulePermissions['user'])){ } $commonRoles = array_intersect($modulePermissions['user_roles'], $userRoles); if(empty($commonRoles)){ - echo "You are not allowed to access this page"; - header("Location:".CLIENT_BASE_URL."logout.php"); + session_start(); + $_SESSION['user'] = null; + session_destroy(); + session_write_close(); + $user = null; + header("Location:".CLIENT_BASE_URL."login.php?f=1&fm=You are not allowed to access this module"); exit(); } @@ -149,8 +153,8 @@ include('configureUIManager.php'); + diff --git a/src/model/models.inc.php b/src/model/models.inc.php index 0c2a21eb..01489c0b 100644 --- a/src/model/models.inc.php +++ b/src/model/models.inc.php @@ -47,6 +47,7 @@ class Setting extends ICEHRM_Record { public function getUserAccess(){ return array(); } + var $_table = 'Settings'; } diff --git a/src/modules.php b/src/modules.php index b847ff6d..5b7cc155 100644 --- a/src/modules.php +++ b/src/modules.php @@ -103,10 +103,6 @@ foreach($ams as $am){ if($addNewPermissions && isset($meta->permissions)){ createPermissions($meta, $dbModule->id); } - - if($dbModule->status == 'Disabled'){ - continue; - } $arr['name'] = $dbModule->name; @@ -140,6 +136,9 @@ foreach($ams as $am){ } includeModuleManager('admin',$am, $arr); + if($dbModule->status == 'Disabled'){ + continue; + } if(!isset($adminModulesTemp[$arr['menu']])){ $adminModulesTemp[$arr['menu']] = array(); @@ -191,10 +190,7 @@ foreach($ams as $am){ if($addNewPermissions && isset($meta->permissions)){ createPermissions($meta, $dbModule->id); } - - if($dbModule->status == 'Disabled'){ - continue; - } + $arr['name'] = $dbModule->name; $arr['label'] = $dbModule->label; @@ -226,6 +222,10 @@ foreach($ams as $am){ } includeModuleManager('modules',$am, $arr); + + if($dbModule->status == 'Disabled'){ + continue; + } if(!isset($userModulesTemp[$arr['menu']])){ $userModulesTemp[$arr['menu']] = array();