<?php
require_once(Path::handlerClassPath() . "WeekHandler.php");
require_once(Path::handlerClassPath() . "EmployeeHandler.php");
require_once(Path::handlerClassPath() . "ProjectHandler.php");
require_once(Path::handlerClassPath() . "BallparkDetailsHandler.php");
require_once(Path::handlerClassPath() . "EmployeeHolidayHandler.php");
require_once(Path::handlerClassPath() . "ProjectDetailsHandler.php");
require_once(Path::handlerClassPath() . "ProjectEmployeeRoleHandler.php");
require_once(Path::handlerClassPath() . "ProjectWeeklyWorkloadHandler.php");
require_once(Path::constantsClassPath() . "ProjectStatusKeys.php");
require_once(Path::constantsClassPath() . "ProjectEmployeeRoleStatus.php");
require_once(Path::utilityClassPath() . "WeekNumberUtility.php");
require_once(Path::validationClassPath() . "InputValidator.php");
require_once(Path::controllerClassPath() . "ControllerInterface.php");
require_once(Path::controllerClassPath() . "Controller.php");
class ViewWorkloadController extends Controller implements ControllerInterface {
private $weekHandler;
private $employeeHandler;
private $ballparkDetailsHandler;
private $projectDetailsHandler;
private $employeeHolidayHandler;
private $projectEmployeeWorkloadHandler;
private $projectEmployeeRoleHandler;
private $projectWeeklyWorkloadHandler;
private $projectHandler;
private $employeeId;
private $projectEmployeeRoles;
private $projectInfo; # Row data
private $availability; # Availability row
private $holidayLoad; # Holiday (miscellanoues) row
private $finishedLoad; # Finished load row
private $earliestDate; # Earliest start date in all projects
private $latestDate; # Earliest end date in all projects
private $startDate; # Start date based on page input, store earliestDate if applicable
private $endDate; # Start date based on page input, store latestDate if applicable
private $errors;
private $workloadWeekStartAndEndDate;
public function init() {
$this->weekHandler = new WeekHandler($this->mysqli);
$this->employeeHandler = new EmployeeHandler($this->mysqli);
$this->ballparkDetailsHandler = new BallparkDetailsHandler($this->mysqli);
$this->projectDetailsHandler = new projectDetailsHandler($this->mysqli);
$this->projectEmployeeRoleHandler = new ProjectEmployeeRoleHandler($this->mysqli);
$this->projectWeeklyWorkloadHandler = new ProjectWeeklyWorkloadHandler($this->mysqli);
$this->employeeHolidayHandler = new EmployeeHoliday($this->mysqli);
$this->projectHandler = new ProjectHandler($this->mysqli);
}
public function setEmployeeId($employeeId) {
$this->employeeId = $employeeId;
}
public function getErrors() {
return $this->errors;
}
private function setError($message) {
$this->errors[] = $message;
}
public function getProjectManager() {
return $this->projectManager;
}
public function getEmployeeIdByEmployeeName($employeeName) {
return $this->employeeHandler->getEmployeeIdByEmployeeName($employeeName);
}
public function processInput() {
if(isset($_POST["refresh"]) ||
(isset($_POST["startdate"]) && isset($_POST["enddate"])) ||
(isset($_GET["startdate"]) && isset($_GET["enddate"]))) {
$this->validateDateInput();
}
$projectStatusIds[] = ProjectStatusKeys::BALLPARK_ACTIVE;
$projectStatusIds[] = ProjectStatusKeys::PROJECT_ACTIVE;
$employeeId = $this->employeeId;
$projectEmployeeRoles = $this->projectEmployeeRoleHandler->
getProjectEmployeeRolesByEmployeeIdAndProjectStatusId($employeeId, $projectStatusIds);
$this->projectEmployeeRoles = $projectEmployeeRoles;
$this->processProjectEmployeeRoles();
# If active project present
if($this->projectInfo) {
$this->processEarliestDate();
$this->processLatestDate();
}
$this->processWeekNumbers();
$this->processProjectEmployeeWorkload();
$this->processFinishedWorkload();
$this->processHolidayLoad();
$this->processAvailability();
}
private function validateDateInput() {
if((isset($_GET["startdate"]) && isset($_GET["enddate"]))) {
$startDate = $_GET["startdate"];
$endDate = $_GET["enddate"];
}
else {
$startDate = $_POST["startdate"];
$endDate = $_POST["enddate"];
}
if(strlen($startDate) < 1 && strlen($endDate) < 1 ) {
$startDate = date('Y/m/d');
$endDate = date('Y/m/d');
}
if(strlen($startDate) < 1 && !(strlen($endDate) < 1)) {
$startDate = $endDate;
}
else if (strlen($startDate < 1)) {
$startDate = date('Y/m/d');
}
$startDateS = strtotime($startDate);
$endDateS = strtotime($endDate);
$dateDiff = $endDateS - $startDateS;
$fullDays = floor($dateDiff/(60*60*24));
if($startDateS > $endDateS) {
$this->setError("Start date must be earlier than end date");
}
else if ($fullDays > 365) {
$this->setError("Total days for comparison must not exceed one year.");
}
$this->startDate = $startDate;
$this->endDate = $endDate;
}
private function processProjectEmployeeRoles() {
$projectEmployeeRoles = $this->projectEmployeeRoles;
$projectInfo = array();
if(!$projectEmployeeRoles) {
$projectDetails["startdate"] = date('Y-m-d');
$projectDetails["enddate"] = date('Y-m-d');
$projectDetails["projectid"] = null;
$projectDetails["name"] = null;
$projectDetails["status"] = null;
$projectInfo[] = $projectDetails;
$this->projectInfo = $projectInfo;
return;
}
foreach($projectEmployeeRoles as $projectEmployeeRole) {
$projectStatusId = $projectEmployeeRole->getProjectStatusId();
$projectId = $projectEmployeeRole->getProjectId();
$projectEmployeeRoleId = $projectEmployeeRole->getProjectEmployeeRoleId();
$projectDetails = array();
$projectDetails["employeeroleid"] = $projectEmployeeRoleId;
$projectDetails["role"] = $projectEmployeeRole->getRoleName();
# Get the project manager from database
$projectManager = $this->projectHandler->getProjectManagerEmployeeByProjectId($projectId);
$projectDetails["managername"] = $projectManager->getEmployeeName();
$projectDetails["managerid"] = $projectManager->getEmployeeId();
if($projectStatusId == ProjectStatusKeys::BALLPARK_ACTIVE) {
$ballpark = $this->ballparkDetailsHandler->getBallparkDetailsByProjectId($projectId);
$projectDetails["startdate"] = $ballpark->getBallparkDetailsStartDate();
$projectDetails["enddate"] = $ballpark->getBallparkDetailsEndDate();
$projectDetails["projectid"] = $projectId;
$projectDetails["name"] = $ballpark->getBallparkDetailsBookingRef();
$projectDetails["status"] = ProjectStatusKeys::BALLPARK_ACTIVE;
}
else if($projectStatusId == ProjectStatusKeys::PROJECT_ACTIVE) {
$project = $this->projectDetailsHandler->getProjectDetailsByProjectId($projectId);
$projectDetails["startdate"] = $project->getProjectDetailsStartDate();
$projectDetails["enddate"] = $project->getProjectDetailsEndDate();
$projectDetails["projectid"] = $projectId;
$projectDetails["name"] = $project->getProjectDetailsName();
$projectDetails["status"] = ProjectStatusKeys::PROJECT_ACTIVE;
}
$projectInfo[] = $projectDetails;
}
$this->projectInfo = $projectInfo;
}
private function processEarliestDate() {
$projectInfo = $this->projectInfo;
$startDate = null;
foreach($projectInfo as $info) {
$infoDate = $info["startdate"];
if(!isset($startDate)) {
$startDate = $infoDate;
continue;
}
if(strtotime($startDate) > strtotime($infoDate)) {
$startDate = $infoDate;
}
}
$this->earliestDate = $startDate;
}
private function processLatestDate() {
$projectInfo = $this->projectInfo;
$endDate = null;
foreach($projectInfo as $info) {
$infoDate = $info["enddate"];
if(!isset($endDate)) {
$endDate = $infoDate;
continue;
}
if(strtotime($endDate) < strtotime($infoDate)) {
$endDate = $infoDate;
}
}
$this->latestDate = $endDate;
}
private function processWeekNumbers() {
if(isset($_POST["refresh"]) || isset($_POST["ajax"]) || isset($_POST["hasrefresh"]) ||
(isset($_GET["startdate"]) && isset($_GET["enddate"]) && !$this->errors)) {
$delimiter = "/"; # Input date format is yyyy/mm/dd
$startDate = $this->startDate;
$endDate = $this->endDate;
}
else {
$delimiter = "-"; # SQL date format is yyyy-mm-dd
$startDate = $this->earliestDate;
$endDate = $this->latestDate;
# If earliest and latest end date exceeds one year, force a shorter span
if($this->isGreaterThanAYear($startDate, $endDate)) {
$endDate = date('Y/m/d', strtotime($startDate ." + 11 months"));
}
# Store information
$this->startDate = $startDate;
$this->endDate = $endDate;
}
$projectWorkloadWeekNumbers =
WeekNumberUtility::computeAndStoreWeekNumbers($startDate, $endDate, $delimiter);
$workloadWeekStartAndEndDate = array();
foreach($projectWorkloadWeekNumbers as $weekNumbers) {
$weekYearArray = explode("-", $weekNumbers);
$weekNumber = $weekYearArray[0];
$year = $weekYearArray[1];
$startDate = WeekNumberUtility::convertWeekNumberToMonday($weekNumber, $year, 'Y/m/d');
$endDate = WeekNumberUtility::getFridayFromMondayDate($startDate, 'Y/m/d');
$startAndEndDate["weeknumber"] = $weekNumber;
$startAndEndDate["year"] = $year;
$startAndEndDate["startdate"] = $startDate;
$startAndEndDate["enddate"] = $endDate;
$workloadWeekStartAndEndDate[] = $startAndEndDate;
}
# Store Workload week numbers and dates
$this->workloadWeekStartAndEndDate = $workloadWeekStartAndEndDate;
}
/**
* Gets the week start and end date, which is generated at method generateData()
* @return <b>mixed[]</b> - Array where: <br/>
* - array[]["weeknumber"] <br/>
* - array[]["year"] <br/>
* - array[]["startdate"] <br/>
* - array[]["enddate"] <br/>
*/
public function getWorkloadWeekStartAndEndDate() {
return $this->workloadWeekStartAndEndDate;
}
/**
* Processes the data for individual project workloads
*/
private function processProjectEmployeeWorkload() {
$weekStartAndEnd = $this->workloadWeekStartAndEndDate;
$projectInfo = $this->projectInfo;
$maxProjects = count($projectInfo);
for($i = 0; $i < $maxProjects; $i++) {
$workload = array();
$isProject = array();
$projectEmployeeRoleId = $projectInfo[$i]["employeeroleid"];
$projectWeeklyWorkloads = $this->projectWeeklyWorkloadHandler->
getProjectWeeklyWorkloadByProjectEmployeeRoleId($projectEmployeeRoleId);
# Loop for each week in the total duration of the timeline
foreach($weekStartAndEnd as $weekDates) {
/**
* @todo Currently loops through the entire project_weekly_workload to compare.
* Very unoptimized.
*/
$load = 0;
$isProj = false;
foreach($projectWeeklyWorkloads as $projectWeeklyWorkload) {
if($projectWeeklyWorkload->getWeekNumber() == $weekDates["weeknumber"]
&& $projectWeeklyWorkload->getWeekYear() == $weekDates["year"]) {
$load += $projectWeeklyWorkload->getProjectWeeklyWorkloadLoad();
$isProj = true;
break;
}
}
$isProject[] = $isProj;
$workload[] = $load;
}
# Appends "Workload" array to project
$projectInfo[$i]["isproject"] = $isProject;
$projectInfo[$i]["workload"] = $workload;
}
$this->projectInfo = $projectInfo;
/*
foreach($projectInfo as $x) {
echo "<hr>";
echo $x["name"] . "-";
echo $x["role"] . "-";
echo $x["projectid"] . "-";
echo count($x["workload"]) . "-";
}
*/
}
private function processFinishedWorkload () {
$finishedLoad = array();
$projectWeeklyWorkloadHandler = $this->projectWeeklyWorkloadHandler;
$employeeId = $this->employeeId;
$weekStartAndEnd = $this->workloadWeekStartAndEndDate;
$projectStatusIds[] = ProjectStatusKeys::BALLPARK_APPROVED;
$projectStatusIds[] = ProjectStatusKeys::BALLPARK_COMPLETED;
$projectStatusIds[] = ProjectStatusKeys::BALLPARK_EXPIRED;
$projectStatusIds[] = ProjectStatusKeys::BALLPARK_CANCELLED;
$projectStatusIds[] = ProjectStatusKeys::PROJECT_CANCELLED;
$projectStatusIds[] = ProjectStatusKeys::PROJECT_COMPLETED;
$startWeekNumber = $weekStartAndEnd[0]["weeknumber"];
$startYear = $weekStartAndEnd[0]["year"];
$max = count($weekStartAndEnd);
$endWeekNumber = $weekStartAndEnd[$max-1]["weeknumber"];
$endYear = $weekStartAndEnd[$max-1]["year"];
$weeklyWorkloads = $projectWeeklyWorkloadHandler->
getProjectWeeklyWorkloadByEmployeeIdAndWeekNumberAndYearRangeAndProjectStatusIds(
$employeeId, $startWeekNumber, $startYear, $endWeekNumber, $endYear, $projectStatusIds);
/**
* Currently unoptimized, but meh
*/
foreach($weekStartAndEnd as $weekDate) {
$origWeekNum = $weekDate["weeknumber"];
$origWeekYear = $weekDate["year"];
$totalLoad = 0;
if($weeklyWorkloads) {
foreach($weeklyWorkloads as $workload) {
$weekYear = $workload->getWeekYear();
$weekNumber = $workload->getWeekNumber();
$load = $workload->getProjectWeeklyWorkloadLoad();
if($origWeekNum == $weekNumber && $origWeekYear == $weekYear) {
$totalLoad += $load;
}
}
}
$totalLoad = round($totalLoad, 2);
$finishedLoad[] = $totalLoad;
}
$this->finishedLoad = $finishedLoad;
}
private function processAvailability() {
$availability = array();
$projectInfo = $this->projectInfo;
$finishedLoad = $this->finishedLoad;
$holidayLoad = $this->holidayLoad;
$maxRow = count($projectInfo);
$maxColumn = count($projectInfo[0]["workload"]);
for($i = 0; $i < $maxColumn; $i++) {
$load = 5;
for($j = 0; $j < $maxRow; $j++) {
$load -= $projectInfo[$j]["workload"][$i];
}
$load -= $finishedLoad[$i];
$load -= $holidayLoad[$i];
$availability[] = round($load,2);
}
$this->availability = $availability;
}
private function processHolidayLoad() {
$holidayLoad = array();
$weekStartAndEnd = $this->workloadWeekStartAndEndDate;
$employeeId = $this->employeeId;
foreach($weekStartAndEnd as $weekDates) {
$load = 0;
$isProj = false;
$startDate = WeekNumberUtility::convertWeekNumberToMonday(
$weekDates["weeknumber"], $weekDates["year"], 'Y/m/d');
$endDate = WeekNumberUtility::getFridayFromMondayDate($startDate, 'Y/m/d');
$load += $this->employeeHolidayHandler->getHolidayLoad($employeeId, $startDate, $endDate);
$holidayLoad[] = $load;
}
$this->holidayLoad = $holidayLoad;
}
private function isGreaterThanAYear($startDate, $endDate) {
$startDateS = strtotime($startDate);
$endDateS = strtotime($endDate);
$dateDiff = $endDateS - $startDateS;
$fullDays = floor($dateDiff/(60*60*24));
if(fullDays > 365)
return true;
return false;
}
public function getProjectInfo() {
return $this->projectInfo;
}
public function getEarliestDate() {
return $this->earliestDate;
}
public function getLatestDate() {
return $this->latestDate;
}
public function getStartDate(){
return $this->startDate;
}
public function getEndDate() {
return $this->endDate;
}
public function getAvailability() {
return $this->availability;
}
public function getFinishedLoad() {
return $this->finishedLoad;
}
public function getHolidayLoad() {
return $this->holidayLoad;
}
public function getEmployee() {
$employeeId = $this->employeeId;
return $this->employeeHandler->getEmployeeByEmployeeId($employeeId);
}
}
?>