Refactor project structure
This commit is contained in:
134
core/src/Attendance/Admin/Api/AttendanceActionManager.php
Normal file
134
core/src/Attendance/Admin/Api/AttendanceActionManager.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
/*
|
||||
This file is part of iCE Hrm.
|
||||
|
||||
iCE Hrm is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
iCE Hrm is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with iCE Hrm. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
------------------------------------------------------------------
|
||||
|
||||
Original work Copyright (c) 2012 [Gamonoid Media Pvt. Ltd]
|
||||
Developer: Thilina Hasantha (thilina.hasantha[at]gmail.com / facebook.com/thilinah)
|
||||
*/
|
||||
namespace Attendance\Admin\Api;
|
||||
|
||||
use Attendance\Common\Model\Attendance;
|
||||
use Classes\BaseService;
|
||||
use Classes\IceResponse;
|
||||
use Classes\LanguageManager;
|
||||
use Classes\SubActionManager;
|
||||
use Utils\LogManager;
|
||||
|
||||
class AttendanceActionManager extends SubActionManager
|
||||
{
|
||||
|
||||
public function savePunch($req)
|
||||
{
|
||||
|
||||
$employee = $this->baseService->getElement('Employee', $req->employee, null, true);
|
||||
$inDateTime = $req->in_time;
|
||||
$inDateArr = explode(" ", $inDateTime);
|
||||
$inDate = $inDateArr[0];
|
||||
$outDateTime = $req->out_time;
|
||||
$outDate = "";
|
||||
if (!empty($outDateTime)) {
|
||||
$outDateArr = explode(" ", $outDateTime);
|
||||
$outDate = $outDateArr[0];
|
||||
}
|
||||
|
||||
$note = $req->note;
|
||||
|
||||
//check if dates are differnet
|
||||
if (!empty($outDate) && $inDate != $outDate) {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
LanguageManager::tran('Attendance entry should be within a single day')
|
||||
);
|
||||
}
|
||||
|
||||
//compare dates
|
||||
if (!empty($outDateTime) && strtotime($outDateTime) <= strtotime($inDateTime)) {
|
||||
return new IceResponse(IceResponse::ERROR, 'Punch-in time should be lesser than Punch-out time');
|
||||
}
|
||||
|
||||
//Find all punches for the day
|
||||
$attendance = new Attendance();
|
||||
$attendanceList = $attendance->Find(
|
||||
"employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ?",
|
||||
array($employee->id,$inDate)
|
||||
);
|
||||
|
||||
foreach ($attendanceList as $attendance) {
|
||||
if (!empty($req->id) && $req->id == $attendance->id) {
|
||||
continue;
|
||||
}
|
||||
if (empty($attendance->out_time) || $attendance->out_time == "0000-00-00 00:00:00") {
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
"There is a non closed attendance entry for today.
|
||||
Please mark punch-out time of the open entry before adding a new one"
|
||||
);
|
||||
} elseif (!empty($outDateTime)) {
|
||||
if (strtotime($attendance->out_time) >= strtotime($outDateTime)
|
||||
&& strtotime($attendance->in_time) <= strtotime($outDateTime)) {
|
||||
//-1---0---1---0 || ---0--1---1---0
|
||||
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
|
||||
} elseif (strtotime($attendance->out_time) >= strtotime($inDateTime)
|
||||
&& strtotime($attendance->in_time) <= strtotime($inDateTime)) {
|
||||
//---0---1---0---1 || ---0--1---1---0
|
||||
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
|
||||
} elseif (strtotime($attendance->out_time) <= strtotime($outDateTime)
|
||||
&& strtotime($attendance->in_time) >= strtotime($inDateTime)) {
|
||||
//--1--0---0--1--
|
||||
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
|
||||
}
|
||||
} else {
|
||||
if (strtotime($attendance->out_time) >= strtotime($inDateTime)
|
||||
&& strtotime($attendance->in_time) <= strtotime($inDateTime)) {
|
||||
//---0---1---0
|
||||
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$attendance = new Attendance();
|
||||
if (!empty($req->id)) {
|
||||
$attendance->Load("id = ?", array($req->id));
|
||||
}
|
||||
$attendance->in_time = $inDateTime;
|
||||
if (empty($outDateTime)) {
|
||||
$attendance->out_time = null;
|
||||
} else {
|
||||
$attendance->out_time = $outDateTime;
|
||||
}
|
||||
|
||||
$attendance->employee = $req->employee;
|
||||
$attendance->note = $note;
|
||||
$ok = $attendance->Save();
|
||||
if (!$ok) {
|
||||
LogManager::getInstance()->info($attendance->ErrorMsg());
|
||||
return new IceResponse(IceResponse::ERROR, "Error occurred while saving attendance");
|
||||
}
|
||||
return new IceResponse(IceResponse::SUCCESS, $attendance);
|
||||
}
|
||||
|
||||
public function getImages($req)
|
||||
{
|
||||
$attendance = BaseService::getInstance()->getElement(
|
||||
'Attendance',
|
||||
$req->id,
|
||||
'{"employee":["Employee","id","first_name+last_name"]}'
|
||||
);
|
||||
return new IceResponse(IceResponse::SUCCESS, $attendance);
|
||||
}
|
||||
}
|
||||
129
core/src/Attendance/Admin/Api/AttendanceAdminManager.php
Normal file
129
core/src/Attendance/Admin/Api/AttendanceAdminManager.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
namespace Attendance\Admin\Api;
|
||||
|
||||
use Attendance\Common\Model\Attendance;
|
||||
use Attendance\Rest\AttendanceRestEndPoint;
|
||||
use Classes\AbstractModuleManager;
|
||||
use Classes\UIManager;
|
||||
|
||||
class AttendanceAdminManager extends AbstractModuleManager
|
||||
{
|
||||
|
||||
public function initializeUserClasses()
|
||||
{
|
||||
}
|
||||
|
||||
public function initializeFieldMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function initializeDatabaseErrorMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function setupModuleClassDefinitions()
|
||||
{
|
||||
$this->addModelClass('Attendance');
|
||||
$this->addModelClass('AttendanceStatus');
|
||||
}
|
||||
|
||||
public function setupRestEndPoints()
|
||||
{
|
||||
\Classes\Macaw::get(REST_API_PATH.'attendance/(:num)', function ($pathParams) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('get', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::get(REST_API_PATH.'attendance', function ($pathParams) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('listAll', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::get(REST_API_PATH.'employee/(:num)/attendance', function ($pathParams) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('listEmployeeAttendance', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::post(REST_API_PATH.'attendance', function ($pathParams) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('post', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::delete(REST_API_PATH.'attendance/(:num)', function ($pathParams) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('delete', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::post(REST_API_PATH.'attendance/punch-in', function ($pathParams) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('punchIn', $pathParams);
|
||||
});
|
||||
|
||||
\Classes\Macaw::get(REST_API_PATH.'employee/(:num)/open-punch-in/(:any)', function ($employeeId, $date) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('getOpenPunch', [$employeeId, $date]);
|
||||
});
|
||||
|
||||
\Classes\Macaw::post(REST_API_PATH.'attendance/punch-out', function ($pathParams) {
|
||||
$restEndPoint = new AttendanceRestEndPoint();
|
||||
$restEndPoint->process('punchOut', $pathParams);
|
||||
});
|
||||
}
|
||||
|
||||
public function getDashboardItemData()
|
||||
{
|
||||
$data = array();
|
||||
$attendance = new Attendance();
|
||||
$data['numberOfAttendanceLastWeek']
|
||||
= $attendance->Count("in_time > '".date("Y-m-d H:i:s", strtotime("-1 week"))."'");
|
||||
if (empty($data['numberOfAttendanceLastWeek'])) {
|
||||
$data['numberOfAttendanceLastWeek'] = 0;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
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")
|
||||
);
|
||||
}
|
||||
|
||||
public function initCalculationHooks()
|
||||
{
|
||||
$this->addCalculationHook(
|
||||
'AttendanceUtil_getTimeWorkedHours',
|
||||
'Total Hours from Attendance',
|
||||
'\\Attendance\\Admin\\Api\\AttendanceUtil',
|
||||
'getTimeWorkedHours'
|
||||
);
|
||||
|
||||
$this->addCalculationHook(
|
||||
'AttendanceUtil_getRegularWorkedHours',
|
||||
'Total Regular Hours from Attendance',
|
||||
'\\Attendance\\Admin\\Api\\AttendanceUtil',
|
||||
'getRegularWorkedHours'
|
||||
);
|
||||
$this->addCalculationHook(
|
||||
'AttendanceUtil_getOverTimeWorkedHours',
|
||||
'Total Overtime Hours from Attendance',
|
||||
'\\Attendance\\Admin\\Api\\AttendanceUtil',
|
||||
'getOverTimeWorkedHours'
|
||||
);
|
||||
$this->addCalculationHook(
|
||||
'AttendanceUtil_getWeeklyRegularWorkedHours',
|
||||
'Total Weekly Regular Hours from Attendance',
|
||||
'\\Attendance\\Admin\\Api\\AttendanceUtil',
|
||||
'getWeeklyBasedRegularHours'
|
||||
);
|
||||
$this->addCalculationHook(
|
||||
'AttendanceUtil_getWeeklyOverTimeWorkedHours',
|
||||
'Total Weekly Overtime Hours from Attendance',
|
||||
'\\Attendance\\Admin\\Api\\AttendanceUtil',
|
||||
'getWeeklyBasedOvertimeHours'
|
||||
);
|
||||
}
|
||||
}
|
||||
25
core/src/Attendance/Admin/Api/AttendanceDashboardManager.php
Normal file
25
core/src/Attendance/Admin/Api/AttendanceDashboardManager.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
namespace Attendance\Admin\Api;
|
||||
|
||||
use Classes\AbstractModuleManager;
|
||||
|
||||
class AttendanceDashboardManager extends AbstractModuleManager
|
||||
{
|
||||
|
||||
public function initializeUserClasses()
|
||||
{
|
||||
}
|
||||
|
||||
public function initializeFieldMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function initializeDatabaseErrorMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function setupModuleClassDefinitions()
|
||||
{
|
||||
$this->addModelClass('Attendance');
|
||||
}
|
||||
}
|
||||
132
core/src/Attendance/Admin/Api/AttendanceUtil.php
Normal file
132
core/src/Attendance/Admin/Api/AttendanceUtil.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/13/17
|
||||
* Time: 8:07 AM
|
||||
*/
|
||||
|
||||
namespace Attendance\Admin\Api;
|
||||
|
||||
use Attendance\Common\Model\Attendance;
|
||||
use Classes\SettingsManager;
|
||||
|
||||
class AttendanceUtil
|
||||
{
|
||||
public function getAttendanceSummary($employeeId, $startDate, $endDate)
|
||||
{
|
||||
$startTime = $startDate." 00:00:00";
|
||||
$endTime = $endDate." 23:59:59";
|
||||
$attendance = new Attendance();
|
||||
$atts = $attendance->Find(
|
||||
"employee = ? and in_time >= ? and out_time <= ?",
|
||||
array($employeeId, $startTime, $endTime)
|
||||
);
|
||||
|
||||
$atCalClassName = SettingsManager::getInstance()->getSetting('Attendance: Overtime Calculation Class');
|
||||
$atCalClassName = '\\Attendance\\Common\\Calculations\\'.$atCalClassName;
|
||||
$atCal = new $atCalClassName();
|
||||
$atSum = $atCal->getDataSeconds($atts, $startDate, true);
|
||||
|
||||
return $atSum;
|
||||
}
|
||||
|
||||
public function getTimeWorkedHours($employeeId, $startDate, $endDate)
|
||||
{
|
||||
$atSum = $this->getAttendanceSummary($employeeId, $startDate, $endDate);
|
||||
return round(($atSum['t']/60)/60, 2);
|
||||
}
|
||||
|
||||
public function getRegularWorkedHours($employeeId, $startDate, $endDate)
|
||||
{
|
||||
$atSum = $this->getAttendanceSummary($employeeId, $startDate, $endDate);
|
||||
return round(($atSum['r']/60)/60, 2);
|
||||
}
|
||||
|
||||
public function getOverTimeWorkedHours($employeeId, $startDate, $endDate)
|
||||
{
|
||||
$atSum = $this->getAttendanceSummary($employeeId, $startDate, $endDate);
|
||||
return round(($atSum['o']/60)/60, 2);
|
||||
}
|
||||
|
||||
public function getWeeklyBasedRegularHours($employeeId, $startDate, $endDate)
|
||||
{
|
||||
$atSum = $this->getWeeklyBasedOvertimeSummary($employeeId, $startDate, $endDate);
|
||||
return round(($atSum['r']/60)/60, 2);
|
||||
}
|
||||
|
||||
public function getWeeklyBasedOvertimeHours($employeeId, $startDate, $endDate)
|
||||
{
|
||||
$atSum = $this->getWeeklyBasedOvertimeSummary($employeeId, $startDate, $endDate);
|
||||
return round(($atSum['o']/60)/60, 2);
|
||||
}
|
||||
|
||||
public function getWeeklyBasedOvertimeSummary($employeeId, $startDate, $endDate)
|
||||
{
|
||||
|
||||
$attendance = new Attendance();
|
||||
$atTimeByWeek = array();
|
||||
|
||||
//Find weeks starting from sunday and ending from saturday in day period
|
||||
|
||||
$weeks = $this->getWeeklyDays($startDate, $endDate);
|
||||
foreach ($weeks as $k => $week) {
|
||||
$startTime = $week[0]." 00:00:00";
|
||||
$endTime = $week[count($week) - 1]." 23:59:59";
|
||||
$atts = $attendance->Find(
|
||||
"employee = ? and in_time >= ? and out_time <= ?",
|
||||
array($employeeId, $startTime, $endTime)
|
||||
);
|
||||
foreach ($atts as $atEntry) {
|
||||
if ($atEntry->out_time == "0000-00-00 00:00:00" || empty($atEntry->out_time)) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($atTimeByWeek[$k])) {
|
||||
$atTimeByWeek[$k] = 0;
|
||||
}
|
||||
|
||||
$diff = strtotime($atEntry->out_time) - strtotime($atEntry->in_time);
|
||||
if ($diff < 0) {
|
||||
$diff = 0;
|
||||
}
|
||||
|
||||
$atTimeByWeek[$k] += $diff;
|
||||
}
|
||||
}
|
||||
|
||||
$overtimeStarts = SettingsManager::getInstance()->getSetting('Attendance: Overtime Start Hour');
|
||||
$overtimeStarts = (is_numeric($overtimeStarts))?floatval($overtimeStarts) * 60 * 60 * 5 : 0;
|
||||
$regTime = 0;
|
||||
$overTime = 0;
|
||||
foreach ($atTimeByWeek as $value) {
|
||||
if ($value > $overtimeStarts) {
|
||||
$regTime += $overtimeStarts;
|
||||
$overTime = $value - $overtimeStarts;
|
||||
} else {
|
||||
$regTime += $value;
|
||||
}
|
||||
}
|
||||
|
||||
return array('r'=>$regTime,'o'=>$overTime);
|
||||
}
|
||||
|
||||
private function getWeeklyDays($startDate, $endDate)
|
||||
{
|
||||
$start = new \DateTime($startDate);
|
||||
$end = new \DateTime($endDate.' 23:59');
|
||||
$interval = new \DateInterval('P1D');
|
||||
$dateRange = new \DatePeriod($start, $interval, $end);
|
||||
|
||||
$weekNumber = 1;
|
||||
$weeks = array();
|
||||
/* @var \DateTime $date */
|
||||
foreach ($dateRange as $date) {
|
||||
$weeks[$weekNumber][] = $date->format('Y-m-d');
|
||||
if ($date->format('w') == 6) {
|
||||
$weekNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
return $weeks;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/13/17
|
||||
* Time: 6:56 PM
|
||||
*/
|
||||
|
||||
namespace Attendance\Common\Calculations;
|
||||
|
||||
use Classes\SettingsManager;
|
||||
|
||||
class BasicOvertimeCalculator
|
||||
{
|
||||
|
||||
public function createAttendanceSummary($atts)
|
||||
{
|
||||
|
||||
$atTimeByDay = array();
|
||||
|
||||
foreach ($atts as $atEntry) {
|
||||
if ($atEntry->out_time == "0000-00-00 00:00:00" || empty($atEntry->out_time)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$atDate = date("Y-m-d", strtotime($atEntry->in_time));
|
||||
|
||||
if (!isset($atTimeByDay[$atDate])) {
|
||||
$atTimeByDay[$atDate] = 0;
|
||||
}
|
||||
|
||||
$diff = strtotime($atEntry->out_time) - strtotime($atEntry->in_time);
|
||||
if ($diff < 0) {
|
||||
$diff = 0;
|
||||
}
|
||||
|
||||
$atTimeByDay[$atDate] += $diff;
|
||||
}
|
||||
|
||||
return $atTimeByDay;
|
||||
}
|
||||
|
||||
public function calculateOvertime($atTimeByDay)
|
||||
{
|
||||
$overtimeStarts = SettingsManager::getInstance()->getSetting('Attendance: Overtime Start Hour');
|
||||
$doubletimeStarts = SettingsManager::getInstance()->getSetting('Attendance: Double time Start Hour');
|
||||
|
||||
$overtimeStarts = (is_numeric($overtimeStarts))?floatval($overtimeStarts)*60*60:0;
|
||||
$doubletimeStarts = (is_numeric($doubletimeStarts))?floatval($doubletimeStarts)*60*60:0;
|
||||
|
||||
$atTimeByDayNew = array();
|
||||
foreach ($atTimeByDay as $k => $v) {
|
||||
$atTimeByDayNewEntry = array("t"=>$v,"r"=>0,"o"=>0,"d"=>0);
|
||||
if ($overtimeStarts > 0 && $v > $overtimeStarts) {
|
||||
$atTimeByDayNewEntry["r"] = $overtimeStarts;
|
||||
if ($doubletimeStarts > 0 && $doubletimeStarts > $overtimeStarts) {
|
||||
//calculate double time
|
||||
if ($v > $doubletimeStarts) {
|
||||
$atTimeByDayNewEntry['d'] = $v - $doubletimeStarts;
|
||||
$atTimeByDayNewEntry['o'] = $doubletimeStarts - $overtimeStarts;
|
||||
} else {
|
||||
$atTimeByDayNewEntry['d'] = 0 ;
|
||||
$atTimeByDayNewEntry['o'] = $v - $overtimeStarts;
|
||||
}
|
||||
} else {
|
||||
//ignore double time
|
||||
$atTimeByDayNewEntry['o'] = $v - $overtimeStarts;
|
||||
}
|
||||
} else {
|
||||
//ignore overtime
|
||||
$atTimeByDayNewEntry['r'] = $v;
|
||||
}
|
||||
|
||||
$atTimeByDayNew[$k] = $atTimeByDayNewEntry;
|
||||
}
|
||||
|
||||
return $atTimeByDayNew;
|
||||
}
|
||||
|
||||
protected function removeAdditionalDays($atSummary, $actualStartDate)
|
||||
{
|
||||
$newAtSummary = array();
|
||||
foreach ($atSummary as $k => $v) {
|
||||
if (strtotime($k) >= strtotime($actualStartDate)) {
|
||||
$newAtSummary[$k] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $newAtSummary;
|
||||
}
|
||||
|
||||
public function getData($atts, $actualStartDate, $aggregate = false)
|
||||
{
|
||||
$atSummary = $this->createAttendanceSummary($atts);
|
||||
$overtime = $this->calculateOvertime($this->removeAdditionalDays($atSummary, $actualStartDate));
|
||||
if ($aggregate) {
|
||||
$overtime = $this->aggregateData($overtime);
|
||||
return $this->convertToHoursAggregated($overtime);
|
||||
} else {
|
||||
return $this->convertToHours($overtime);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDataSeconds($atts, $actualStartDate, $aggregate = false)
|
||||
{
|
||||
$atSummary = $this->createAttendanceSummary($atts);
|
||||
$overtime = $this->calculateOvertime($this->removeAdditionalDays($atSummary, $actualStartDate));
|
||||
if ($aggregate) {
|
||||
$overtime = $this->aggregateData($overtime);
|
||||
return $overtime;
|
||||
} else {
|
||||
return $overtime;
|
||||
}
|
||||
}
|
||||
|
||||
public function convertToHours($overtime)
|
||||
{
|
||||
foreach ($overtime as $k => $v) {
|
||||
$overtime[$k]['t'] = $this->convertToHoursAndMinutes($overtime[$k]['t']);
|
||||
$overtime[$k]['r'] = $this->convertToHoursAndMinutes($overtime[$k]['r']);
|
||||
$overtime[$k]['o'] = $this->convertToHoursAndMinutes($overtime[$k]['o']);
|
||||
$overtime[$k]['d'] = $this->convertToHoursAndMinutes($overtime[$k]['d']);
|
||||
}
|
||||
|
||||
return $overtime;
|
||||
}
|
||||
|
||||
public function convertToHoursAggregated($overtime)
|
||||
{
|
||||
$overtime['t'] = $this->convertToHoursAndMinutes($overtime['t']);
|
||||
$overtime['r'] = $this->convertToHoursAndMinutes($overtime['r']);
|
||||
$overtime['o'] = $this->convertToHoursAndMinutes($overtime['o']);
|
||||
$overtime['d'] = $this->convertToHoursAndMinutes($overtime['d']);
|
||||
|
||||
return $overtime;
|
||||
}
|
||||
|
||||
protected function aggregateData($overtime)
|
||||
{
|
||||
$ag = array("t"=>0,"r"=>0,"o"=>0,"d"=>0);
|
||||
foreach ($overtime as $k => $v) {
|
||||
$ag['t'] += $v['t'];
|
||||
$ag['r'] += $v['r'];
|
||||
$ag['o'] += $v['o'];
|
||||
$ag['d'] += $v['d'];
|
||||
}
|
||||
|
||||
return $ag;
|
||||
}
|
||||
|
||||
public function convertToHoursAndMinutes($val)
|
||||
{
|
||||
$sec = $val % 60;
|
||||
$minutesTot = ($val - $sec)/60;
|
||||
|
||||
$minutes = $minutesTot % 60;
|
||||
$hours = ($minutesTot - $minutes)/60;
|
||||
|
||||
if ($hours < 10) {
|
||||
$hours = "0".$hours;
|
||||
}
|
||||
if ($minutes < 10) {
|
||||
$minutes = "0".$minutes;
|
||||
}
|
||||
|
||||
return $hours.":".$minutes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
namespace Attendance\Common\Calculations;
|
||||
|
||||
use Classes\SettingsManager;
|
||||
|
||||
class CaliforniaOvertimeCalculator extends BasicOvertimeCalculator
|
||||
{
|
||||
|
||||
public function getData($atts, $actualStartDate, $aggregate = false)
|
||||
{
|
||||
|
||||
if (count($atts) == 0) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$atSummary = $this->createAttendanceSummary($atts);
|
||||
$overtime = $this->calculateOvertime($atSummary);
|
||||
|
||||
$workWeekStartDate = SettingsManager::getInstance()->getSetting('Attendance: Work Week Start Day');
|
||||
|
||||
//TODO - just assume a work week from Sunday to Saturday
|
||||
|
||||
//Find first Sunday in array
|
||||
$firstDate = null;
|
||||
$prvDate = null;
|
||||
$consecutiveWorkDays = 1;
|
||||
foreach ($overtime as $k => $v) {
|
||||
if ($firstDate == null) {
|
||||
$dw = date("w", strtotime($k));
|
||||
if ($dw == $workWeekStartDate) {
|
||||
$firstDate = $k;
|
||||
}
|
||||
}
|
||||
|
||||
if ($firstDate != null) {
|
||||
if ($prvDate != null && date('Y-m-d', strtotime('-1 day', strtotime($k))) == $prvDate) {
|
||||
$consecutiveWorkDays++;
|
||||
if ($consecutiveWorkDays == 7) {
|
||||
//This is a double time day
|
||||
$overtime[$k]['d'] = $overtime[$k]['d'] + $overtime[$k]['o'];
|
||||
$overtime[$k]['o'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Resetting $consecutiveWorkDays at the start of the work week
|
||||
if ($prvDate != null && date("w", strtotime($k)) == $workWeekStartDate) {
|
||||
$consecutiveWorkDays = 1;
|
||||
$prvDate = null;
|
||||
}
|
||||
|
||||
$prvDate = $k;
|
||||
}
|
||||
}
|
||||
|
||||
$overtime = $this->removeAdditionalDays($overtime, $actualStartDate);
|
||||
if ($aggregate) {
|
||||
$overtime = $this->aggregateData($overtime);
|
||||
return $this->convertToHoursAggregated($overtime);
|
||||
} else {
|
||||
return $this->convertToHours($overtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
core/src/Attendance/Common/Model/Attendance.php
Normal file
36
core/src/Attendance/Common/Model/Attendance.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/13/17
|
||||
* Time: 8:04 AM
|
||||
*/
|
||||
|
||||
namespace Attendance\Common\Model;
|
||||
|
||||
use Model\BaseModel;
|
||||
|
||||
class Attendance extends BaseModel
|
||||
{
|
||||
public $table = 'Attendance';
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
139
core/src/Attendance/Common/Model/AttendanceStatus.php
Normal file
139
core/src/Attendance/Common/Model/AttendanceStatus.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/13/17
|
||||
* Time: 8:06 AM
|
||||
*/
|
||||
|
||||
namespace Attendance\Common\Model;
|
||||
|
||||
use Classes\SettingsManager;
|
||||
use Employees\Common\Model\Employee;
|
||||
use Model\BaseModel;
|
||||
|
||||
class AttendanceStatus extends BaseModel
|
||||
{
|
||||
public $table = 'Attendance';
|
||||
|
||||
public function getRecentAttendanceEntries($limit)
|
||||
{
|
||||
$shift = intval(SettingsManager::getInstance()->getSetting("Attendance: Shift (Minutes)"));
|
||||
$attendance = new Attendance();
|
||||
$attendanceToday = $attendance->Find("1 = 1 order by in_time desc limit ".$limit, array());
|
||||
$employees = array();
|
||||
foreach ($attendanceToday as $atEntry) {
|
||||
$entry = new \stdClass();
|
||||
$entry->id = $atEntry->employee;
|
||||
$dayArr = explode(" ", $atEntry->in_time);
|
||||
$day = $dayArr[0];
|
||||
if ($atEntry->out_time == "0000-00-00 00:00:00" || empty($atEntry->out_time)) {
|
||||
if (strtotime($atEntry->in_time) < (time() + $shift * 60) && $day == date("Y-m-d")) {
|
||||
$entry->status = "Clocked In";
|
||||
$entry->statusId = 0;
|
||||
$entry->color = 'green';
|
||||
|
||||
$employee = new Employee();
|
||||
$employee->Load("id = ?", array($entry->id));
|
||||
$entry->employee = $employee->first_name." ".$employee->last_name;
|
||||
$employees[$entry->id] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($employees[$entry->id])) {
|
||||
$employee = new Employee();
|
||||
$employee->Load("id = ?", array($entry->id));
|
||||
if ($day == date("Y-m-d")) {
|
||||
$entry->status = "Clocked Out";
|
||||
$entry->statusId = 1;
|
||||
$entry->color = 'yellow';
|
||||
} else {
|
||||
$entry->status = "Not Clocked In";
|
||||
$entry->statusId = 2;
|
||||
$entry->color = 'gray';
|
||||
}
|
||||
$entry->employee = $employee->first_name." ".$employee->last_name;
|
||||
$employees[$entry->id] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($employees);
|
||||
}
|
||||
// @codingStandardsIgnoreStart
|
||||
public function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
|
||||
{
|
||||
// @codingStandardsIgnoreEnd
|
||||
$shift = intval(SettingsManager::getInstance()->getSetting("Attendance: Shift (Minutes)"));
|
||||
$employee = new Employee();
|
||||
$data = array();
|
||||
$employees = $employee->Find("1=1");
|
||||
|
||||
$attendance = new Attendance();
|
||||
$attendanceToday = $attendance->Find("date(in_time) = ?", array(date("Y-m-d")));
|
||||
$attendanceData = array();
|
||||
//Group by employee
|
||||
foreach ($attendanceToday as $attendance) {
|
||||
if (isset($attendanceData[$attendance->employee])) {
|
||||
$attendanceData[$attendance->employee][] = $attendance;
|
||||
} else {
|
||||
$attendanceData[$attendance->employee] = array($attendance);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($employees as $employee) {
|
||||
$entry = new \stdClass();
|
||||
$entry->id = $employee->id;
|
||||
$entry->employee = $employee->id;
|
||||
|
||||
if (isset($attendanceData[$employee->id])) {
|
||||
$attendanceEntries = $attendanceData[$employee->id];
|
||||
foreach ($attendanceEntries as $atEntry) {
|
||||
if ($atEntry->out_time == "0000-00-00 00:00:00" || empty($atEntry->out_time)) {
|
||||
if (strtotime($atEntry->in_time) < time() + $shift * 60) {
|
||||
$entry->status = "Clocked In";
|
||||
$entry->statusId = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($entry->status)) {
|
||||
$entry->status = "Clocked Out";
|
||||
$entry->statusId = 1;
|
||||
}
|
||||
} else {
|
||||
$entry->status = "Not Clocked In";
|
||||
$entry->statusId = 2;
|
||||
}
|
||||
|
||||
$data[] = $entry;
|
||||
}
|
||||
|
||||
function cmp($a, $b)
|
||||
{
|
||||
return $a->statusId - $b->statusId;
|
||||
}
|
||||
usort($data, "cmp");
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
189
core/src/Attendance/User/Api/AttendanceActionManager.php
Normal file
189
core/src/Attendance/User/Api/AttendanceActionManager.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/18/17
|
||||
* Time: 5:05 AM
|
||||
*/
|
||||
|
||||
namespace Attendance\User\Api;
|
||||
|
||||
use Attendance\Common\Model\Attendance;
|
||||
use AttendanceSheets\Common\Model\EmployeeAttendanceSheet;
|
||||
use Classes\BaseService;
|
||||
use Classes\IceConstants;
|
||||
use Classes\IceResponse;
|
||||
use Classes\SettingsManager;
|
||||
use Classes\SubActionManager;
|
||||
use TimeSheets\Common\Model\EmployeeTimeSheet;
|
||||
use Utils\LogManager;
|
||||
|
||||
class AttendanceActionManager extends SubActionManager
|
||||
{
|
||||
|
||||
public function getPunch($req)
|
||||
{
|
||||
$date = $req->date;
|
||||
$arr = explode(" ", $date);
|
||||
$date = $arr[0];
|
||||
|
||||
$employee = $this->baseService->getElement('Employee', $this->getCurrentProfileId(), null, true);
|
||||
|
||||
//Find any open punch
|
||||
$attendance = new Attendance();
|
||||
$attendance->Load(
|
||||
"employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ? and (out_time is NULL
|
||||
or out_time = '0000-00-00 00:00:00')",
|
||||
array($employee->id,$date)
|
||||
);
|
||||
|
||||
if ($attendance->employee == $employee->id) {
|
||||
//found an open punch
|
||||
return new IceResponse(IceResponse::SUCCESS, $attendance);
|
||||
} else {
|
||||
return new IceResponse(IceResponse::SUCCESS, null);
|
||||
}
|
||||
}
|
||||
|
||||
public function savePunch($req)
|
||||
{
|
||||
|
||||
$useServerTime = SettingsManager::getInstance()->getSetting('Attendance: Use Department Time Zone');
|
||||
$currentEmployeeTimeZone = BaseService::getInstance()->getCurrentEmployeeTimeZone();
|
||||
|
||||
if ($useServerTime == '1' && !empty($currentEmployeeTimeZone)) {
|
||||
date_default_timezone_set('Asia/Colombo');
|
||||
|
||||
$date = new \DateTime("now", new \DateTimeZone('Asia/Colombo'));
|
||||
|
||||
$date->setTimezone(new \DateTimeZone($currentEmployeeTimeZone));
|
||||
$req->time = $date->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
$req->date = $req->time;
|
||||
|
||||
//check if there is an open punch
|
||||
/* @var \Attendance\Common\Model\Attendance */
|
||||
$openPunch = $this->getPunch($req)->getData();
|
||||
|
||||
if (empty($openPunch)) {
|
||||
$openPunch = new Attendance();
|
||||
}
|
||||
|
||||
$dateTime = $req->date;
|
||||
$arr = explode(" ", $dateTime);
|
||||
$date = $arr[0];
|
||||
|
||||
$employee = $this->baseService->getElement('Employee', $this->getCurrentProfileId(), null, true);
|
||||
|
||||
//check if dates are differnet
|
||||
$arr = explode(" ", $openPunch->in_time);
|
||||
$inDate = $arr[0];
|
||||
if (!empty($openPunch->in_time) && $inDate != $date) {
|
||||
return new IceResponse(IceResponse::ERROR, "Attendance entry should be within a single day");
|
||||
}
|
||||
|
||||
//compare dates
|
||||
if (!empty($openPunch->in_time) && strtotime($dateTime) <= strtotime($openPunch->in_time)) {
|
||||
return new IceResponse(IceResponse::ERROR, "Punch-in time should be lesser than Punch-out time");
|
||||
}
|
||||
|
||||
//Find all punches for the day
|
||||
$attendance = new Attendance();
|
||||
$attendanceList = $attendance->Find(
|
||||
"employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ?",
|
||||
array($employee->id,$date)
|
||||
);
|
||||
|
||||
foreach ($attendanceList as $attendance) {
|
||||
if (!empty($openPunch->in_time)) {
|
||||
if ($openPunch->id == $attendance->id) {
|
||||
continue;
|
||||
}
|
||||
if (strtotime($attendance->out_time) >= strtotime($dateTime)
|
||||
&& strtotime($attendance->in_time) <= strtotime($dateTime)
|
||||
) {
|
||||
//-1---0---1---0 || ---0--1---1---0
|
||||
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
|
||||
} elseif (strtotime($attendance->out_time) >= strtotime($openPunch->in_time)
|
||||
&& strtotime($attendance->in_time) <= strtotime($openPunch->in_time)
|
||||
) {
|
||||
//---0---1---0---1 || ---0--1---1---0
|
||||
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
|
||||
} elseif (strtotime($attendance->out_time) <= strtotime($dateTime)
|
||||
&& strtotime($attendance->in_time) >= strtotime($openPunch->in_time)
|
||||
) {
|
||||
//--1--0---0--1--
|
||||
return new IceResponse(
|
||||
IceResponse::ERROR,
|
||||
"Time entry is overlapping with an existing one ".$attendance->id
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (strtotime($attendance->out_time) >= strtotime($dateTime)
|
||||
&& strtotime($attendance->in_time) <= strtotime($dateTime)
|
||||
) {
|
||||
//---0---1---0
|
||||
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($openPunch->in_time)) {
|
||||
$openPunch->out_time = $dateTime;
|
||||
$openPunch->note = $req->note;
|
||||
$openPunch->image_out = $req->image;
|
||||
$this->baseService->audit(IceConstants::AUDIT_ACTION, "Punch Out \ time:".$openPunch->out_time);
|
||||
} else {
|
||||
$openPunch->in_time = $dateTime;
|
||||
//$openPunch->out_time = '0000-00-00 00:00:00';
|
||||
$openPunch->note = $req->note;
|
||||
$openPunch->image_in = $req->image;
|
||||
$openPunch->employee = $employee->id;
|
||||
$this->baseService->audit(IceConstants::AUDIT_ACTION, "Punch In \ time:".$openPunch->in_time);
|
||||
}
|
||||
$ok = $openPunch->Save();
|
||||
|
||||
if (!$ok) {
|
||||
LogManager::getInstance()->info($openPunch->ErrorMsg());
|
||||
return new IceResponse(IceResponse::ERROR, "Error occured while saving attendance");
|
||||
}
|
||||
return new IceResponse(IceResponse::SUCCESS, $openPunch);
|
||||
}
|
||||
|
||||
public function createPreviousAttendnaceSheet($req)
|
||||
{
|
||||
$employee = $this->baseService->getElement('Employee', $this->getCurrentProfileId(), null, true);
|
||||
|
||||
$timeSheet = new EmployeeAttendanceSheet();
|
||||
$timeSheet->Load("id = ?", array($req->id));
|
||||
if ($timeSheet->id != $req->id) {
|
||||
return new IceResponse(IceResponse::ERROR, "Attendance Sheet not found");
|
||||
}
|
||||
|
||||
if ($timeSheet->employee != $employee->id) {
|
||||
return new IceResponse(IceResponse::ERROR, "You don't have permissions to add this Attendance Sheet");
|
||||
}
|
||||
|
||||
$end = date("Y-m-d", strtotime("last Saturday", strtotime($timeSheet->date_start)));
|
||||
$start = date("Y-m-d", strtotime("last Sunday", strtotime($end)));
|
||||
|
||||
$tempTimeSheet = new EmployeeTimeSheet();
|
||||
$tempTimeSheet->Load("employee = ? and date_start = ?", array($employee->id, $start));
|
||||
if ($employee->id == $tempTimeSheet->employee) {
|
||||
return new IceResponse(IceResponse::ERROR, "Attendance Sheet already exists");
|
||||
}
|
||||
|
||||
$newTimeSheet = new EmployeeTimeSheet();
|
||||
$newTimeSheet->employee = $employee->id;
|
||||
$newTimeSheet->date_start = $start;
|
||||
$newTimeSheet->date_end = $end;
|
||||
$newTimeSheet->status = "Pending";
|
||||
$ok = $newTimeSheet->Save();
|
||||
if (!$ok) {
|
||||
LogManager::getInstance()->info("Error creating time sheet : ".$newTimeSheet->ErrorMsg());
|
||||
return new IceResponse(IceResponse::ERROR, "Error creating Attendance Sheet");
|
||||
}
|
||||
|
||||
return new IceResponse(IceResponse::SUCCESS, "");
|
||||
}
|
||||
}
|
||||
27
core/src/Attendance/User/Api/AttendanceModulesManager.php
Normal file
27
core/src/Attendance/User/Api/AttendanceModulesManager.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace Attendance\User\Api;
|
||||
|
||||
use Classes\AbstractModuleManager;
|
||||
|
||||
class AttendanceModulesManager extends AbstractModuleManager
|
||||
{
|
||||
|
||||
public function initializeUserClasses()
|
||||
{
|
||||
if (defined('MODULE_TYPE') && MODULE_TYPE != 'admin') {
|
||||
$this->addUserClass("Attendance");
|
||||
}
|
||||
}
|
||||
|
||||
public function initializeFieldMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function initializeDatabaseErrorMappings()
|
||||
{
|
||||
}
|
||||
|
||||
public function setupModuleClassDefinitions()
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user