t3chguy
asked on
Generating Future dates based on condition
I am working on a project management system and I am trying to get an estimated start date based on the previous projects length and duration. I am putting a "dummy" project in the system with a completion day to help base the future dates off of.
I want each project to look at the previous projects completion date. If that is not set, then it should look at the dates table and see if there are any dates that have been added and add the task length's accordingly.
The dates that are held in the dates table are the start date (which is set by the programmer who will press a start button to begin a project), a pause date (which can be set by the programmer if the project is going on a temporary hold), a resume date, (which will be again set by the programmer when the paused project will be resumed).
The code below is basing all projects based off of the completion date, and is not looking at the previous project to calculate dates.
helpDesk-projectAssignments.sql
helpDesk-projectDates.sql
helpDesk-projectList.sql
I want each project to look at the previous projects completion date. If that is not set, then it should look at the dates table and see if there are any dates that have been added and add the task length's accordingly.
The dates that are held in the dates table are the start date (which is set by the programmer who will press a start button to begin a project), a pause date (which can be set by the programmer if the project is going on a temporary hold), a resume date, (which will be again set by the programmer when the paused project will be resumed).
The code below is basing all projects based off of the completion date, and is not looking at the previous project to calculate dates.
foreach($programmers AS $programmer)
{
//Set End Date for last completed project!
$lastCompletedProject = lastCompletedProject($programmer);
echo 'Last Completed Project: ' . $lastCompletedProject . '<br />';
//Get Projects
$getProjects = mysql_query("SELECT helpDesk_projectList.id, createdFor, projectName, projectPriority, projectStatus, programmerAssigned
FROM helpDesk_projectList
LEFT JOIN helpDesk_projectAssignments ON helpDesk_projectList.id = helpDesk_projectAssignments.projectId
WHERE (projectStatus = '1' OR projectStatus = '2' OR projectStatus = '3') and programmerAssigned = '".$programmer."'") or die("Cannot get current projects: " . mysql_error());
if(mysql_num_rows($getProjects) > 0)
{
$i = 0;
$prevRow = 0;
while($pData = mysql_fetch_assoc($getProjects))
{
//Sum Days of Tasks for each project
$getTasks = mysql_query("SELECT SUM(taskLength) as taskLength FROM helpDesk_projectTasks WHERE projectId = '".$pData['id']."'") or die("Cannot get Tasks: " . mysql_error());
if(mysql_num_rows($getTasks) > 0)
{
while($taskData = mysql_fetch_assoc($getTasks))
{
$taskLength = $taskData['taskLength'];
}
}
//Temp BS
$deadlineDate = date("Y-m-d", strtotime($projectLengthMinusOne . ' weekdays', strtotime($startDate)));
//Check for any other projects that may have dates associated with them.
$checkProjects = mysql_query("SELECT actionDate, actionType FROM helpDesk_projectDates WHERE projectId = '".$pData['id']."' AND actionType <> '1'") or die("Cannot check projects: " . mysql_error());
if(mysql_num_rows($checkProjects) > 0)
{
while($cpData = mysql_fetch_assoc($checkProjects))
{
//add dates to the last action date.
$lastActionDate = $cpData['actionDate'];
$nextStart = 'duh' . date("Y-m-d", strtotime($taskLength . ' weekdays', strtotime($lastActionDate)));
}
}
else
{
if($prevRow == $currentRow)
{
//Last completed + 1
$nextDay = date("Y-m-d", strtotime('+1 weekday', strtotime($lastCompletedProject)));
}
else
{
$nextDay = 'Not sure??';
}
//Add dates to last completed date.
$endDate = 'lol ' . date("Y-m-d", strtotime($taskLength . ' weekdays', strtotime($nextDay)));
}
//Add Task Length to prevoius project Completion Date
echo '<tr>
<td ' . $row_color . '>'.$pData['id'] . '</td>
<td ' . $row_color . '>'.$pData['projectName'] . '</td>
<td ' . $row_color . '>'.getCkname($pData['programmerAssigned']) . '</td>
<td ' . $row_color . '>'.$pData['projectPriority'] . '</td>
<td ' . $row_color . '>'.$estimatedStart . '</td>
<td ' . $row_color . '>'.$estimatedEnd . '</td>
<td ' . $row_color . '>'.$taskLength . '</td>
<td ' . $row_color . '>'.$nextDay . '</td>
<td ' . $row_color . '>'.$endDate . '</td>
<td ' . $row_color . '><span class="boldblacklinks"><a href="editProject.php?projectId='.$projectId.'" class="iframetall">Edit</a></span></td>
</tr>';
$prevRow = $currentRow;
}
}
}
Screenshot.pnghelpDesk-projectAssignments.sql
helpDesk-projectDates.sql
helpDesk-projectList.sql
ASKER
Not so much date arithmetic, but how can I use the last date generated to calculate future dates?
For example, in my screenshot, The Dashboard Updates project starts on 10-15 and has a duration of two days. That would mean that project Test 2 should start on 10-18 and last for three days for an end date of 10-21. Right now, its basing all start and end dates based off of the same date which is 10-14.
The question is about iterating dates based on the previous row's values.
For example, in my screenshot, The Dashboard Updates project starts on 10-15 and has a duration of two days. That would mean that project Test 2 should start on 10-18 and last for three days for an end date of 10-21. Right now, its basing all start and end dates based off of the same date which is 10-14.
The question is about iterating dates based on the previous row's values.
That sounds like date arithmetic to me. I'll see if I can give you an example. It won't use a data base, but the step from rows in a query results set to the code I show will not be very big at all.
Please see: http://www.laprbass.com/RAY_temp_t3chguy.php
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_201-Handling-date-and-time-in-PHP-and-MySQL.html
<?php // RAY_temp_t3chguy.php 2013-10-16
error_reporting(E_ALL);
echo '<pre>';
// SCHEDULE BASED ON CONSECUTIVE TASKS
// http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28268506.html#a39576941
// USE THIS TO SIMULATE A SET OF TASK DURATIONS
$tasks = array
( 'one' => 2
, 'two' => 3
, 'tre' => 4
, 'for' => 1
, 'fiv' => 2
)
;
// WE WILL CAPTURE THE TASK START AND END DAYS HERE
$out = array();
// OUR STARTING DAY WILL BE TOMORROW
$alpha = date('Y-m-d', strtotime('Tomorrow'));
// ADD IN THE TASKS
foreach ($tasks as $item => $num)
{
// THE NUMBER OF WHOLE DAYS
$omega = date('Y-m-d', strtotime($alpha . " + $num DAYS - 1 SECOND"));
// SAVE THE RESULTS
$ndx = $item . "($num days)";
$out[$ndx] = array("Start" => $alpha, "Ended" => $omega);
// START THE NEXT TASK ON THE DAY FOLLOWING THE PRIOR COMPLETION
$alpha = date('Y-m-d', strtotime($omega . " + 1 DAY"));
}
print_r($out);
At some point you may also want to consider weekends and holidays as gaps in the schedule. See practical application #9 in this article.https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_201-Handling-date-and-time-in-PHP-and-MySQL.html
ASKER
That part I understand, but do not understand how to apply that to a while loop for my specific use.
Are you wanting to update the data base table with start / end dates? Or are you looking to insert new rows?
ASKER
Neither, hoping just to do this dynamically in the code.
Looking at this...
Any chance you want something like this?
$nextStart = 'duh' . date("Y-m-d", strtotime($taskLength . ' weekdays', strtotime($lastActionDate)));
Not sure what effect the 'duh' is having on the process, but if it's getting carried forward into a future computation, it won't be helpful.Any chance you want something like this?
// MAKE ISO-8601 OF THE LAST DATE + 1
$lastActionDate = date('Y-m-d', strtotime($lastActionDate));
// ADD WEEK DAYS
$nextStart = date('Y-m-d', strtotime($lastActionDate . " + $taskLength WEEKDAYS"));
If that's not it, please show me an isolated example of the while() loop with a small test set in an array.
ASKER
Programmer 1 had a last completion date of 2013-10-14
Project ID 3 should start on 10-15 and have a duration of 2 days ending on 10/16.
Project ID 5 should start on 10-17 and have a duration of 3 days ending on 10/20.
Project ID 3 should start on 10-15 and have a duration of 2 days ending on 10/16.
Project ID 5 should start on 10-17 and have a duration of 3 days ending on 10/20.
$getProjects = mysql_query("SELECT helpDesk_projectList.id, createdFor, projectName, projectPriority, projectStatus, programmerAssigned
FROM helpDesk_projectList
LEFT JOIN helpDesk_projectAssignments ON helpDesk_projectList.id = helpDesk_projectAssignments.projectId
WHERE (projectStatus = '1' OR projectStatus = '2' OR projectStatus = '3') and programmerAssigned = '".$programmer."'") or die("Cannot get current projects: " . mysql_error());
if(mysql_num_rows($getProjects) > 0)
{
$i = 0;
$prevRow = 0;
while($pData = mysql_fetch_assoc($getProjects))
{
//Sum Days of Tasks for each project
$getTasks = mysql_query("SELECT SUM(taskLength) as taskLength FROM helpDesk_projectTasks WHERE projectId = '".$pData['id']."'") or die("Cannot get Tasks: " . mysql_error());
if(mysql_num_rows($getTasks) > 0)
{
while($taskData = mysql_fetch_assoc($getTasks))
{
$taskLength = $taskData['taskLength'];
}
}
//Check for any other projects that may have dates associated with them.
$checkProjects = mysql_query("SELECT actionDate, actionType FROM helpDesk_projectDates WHERE projectId = '".$pData['id']."' AND actionType <> '1'") or die("Cannot check projects: " . mysql_error());
if(mysql_num_rows($checkProjects) > 0)
{
while($cpData = mysql_fetch_assoc($checkProjects))
{
//add dates to the last action date.
$lastActionDate = $cpData['actionDate'];
$nextStart = date("Y-m-d", strtotime($taskLength . ' weekdays', strtotime($lastActionDate)));
}
}
else
{
//Last completed + 1
$nextDay = date("Y-m-d", strtotime('+1 weekday', strtotime($lastCompletedProject)));
}
//Add dates to last completed date.
$endDate = date('Y-m-d', strtotime($alpha . " + $taskLength DAYS - 1 SECOND"));
// MAKE ISO-8601 OF THE LAST DATE + 1
$lastActionDate = date('Y-m-d', strtotime($nextDay));
// ADD WEEK DAYS
$nextEnd = date('Y-m-d', strtotime($lastActionDate . " + $taskLength WEEKDAYS"));
//Add Task Length to prevoius project Completion Date
echo '<tr>
<td ' . $row_color . '>'.$pData['id'] . '</td>
<td ' . $row_color . '>'.$pData['projectName'] . '</td>
<td ' . $row_color . '>'.getCkname($pData['programmerAssigned']) . '</td>
<td ' . $row_color . '>'.$lastActionDate . '</td>
<td ' . $row_color . '>'.$nextEnd . '</td>
<td ' . $row_color . '><span class="boldblacklinks"><a href="editProject.php?projectId='.$projectId.'" class="iframetall">Edit</a></span></td>
</tr>';
$prevRow = $currentRow;
}
}
}
Please add error_reporting(-1) to the top of this script so we can be sure that it's not relying on any undefined variables.
This is line 34:
This is line 34:
$nextStart = date("Y-m-d", strtotime($taskLength . ' weekdays', strtotime($lastActionDate)));
What is the value that the script creates in $nextStart? Please print it out with var_dump() so we can see what is begin created there.
ASKER
$nextStart returns
NULL
NULL
NULL
That's kind of what I expected. It looks like the intent of that line of code is to add some number of weekdays (identified in the variable $taskLength) to a date identified in the variable $lastActionDate. If that's a fair explanation, please try that line like this and let's see what var_dump() can tell us after the code change.
$nextStart = date("Y-m-d", strtotime($lastActionDate . " + $taskLength weekdays"));
Please correct any typos - I cannot test any of this, so I'm coding without a net.
ASKER
It still returns NULL. Even though the code above it, ($lastActionDate) is not empty.
There is something else going wrong here. Neither of the methods of computing the future date return NULL.
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/PHP_Databases/A_11177-PHP-MySQL-Deprecated-as-of-PHP-5-5-0.html
<?php // RAY_temp_t3chguy_1.php 2013-10-16
error_reporting(E_ALL);
echo '<pre>';
// SCHEDULE BASED ON CONSECUTIVE TASKS
// http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28268506.html#a39576941
$taskLength = 4;
$lastActionDate = '2013-10-16';
$nextStart = date("Y-m-d", strtotime($taskLength . ' weekdays', strtotime($lastActionDate)));
var_dump($nextStart);
$nextStart = date("Y-m-d", strtotime($lastActionDate . " + $taskLength weekdays"));
var_dump($nextStart);
I'm beginning to think there is a program logic error that is skipping some or all of the code. It may need to be rewritten to find the error. Here's an example of the sort of code that should be refactored, and an example of how to run queries and show the errors, if any.<?php // RAY_temp_t3chguy_3.php 2013-10-16
error_reporting(E_ALL);
echo '<pre>';
// SCHEDULE BASED ON CONSECUTIVE TASKS
// http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28268506.html#a39576941
// WHAT WE HAVE
$getTasks = mysql_query("SELECT SUM(taskLength) as taskLength FROM helpDesk_projectTasks WHERE projectId = '".$pData['id']."'") or die("Cannot get Tasks: " . mysql_error());
if(mysql_num_rows($getTasks) > 0)
// THIS IS MORE LIKE WHAT WE NEED
$getTasksQry = "SELECT SUM(taskLength) as taskLength FROM helpDesk_projectTasks WHERE projectId = '{$pData["id"]}' ";
$getTasks = mysql_query($getTasksQry);
if (!$getTasks)
{
$err = "<br>FAIL: $getTasksQry";
$err .= "<br>ERRNO: " . mysql_errno();
$err .= "<br>ERROR: " . mysql_error();
trigger_error($err, E_USER_ERROR);
}
$numTasks = mysql_num_rows($getTasks);
if ($numTasks)
{
echo "<br>getTasksQry FOUND $numTasks ROWS";
}
else
{
echo "<br>getTasksQry FOUND NO ROWS";
}
This article shows how to use PHP and MySQL together. You're going to have to convert all of the procedural MySQL to MySQLi or PDO anyway, might as well start with good examples of how to do it.https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/PHP_Databases/A_11177-PHP-MySQL-Deprecated-as-of-PHP-5-5-0.html
ASKER
Ok, I moved your code into my pre-existing block.
There are three projects in the system.
Running your code returned the following:
getTasksQry FOUND 1 ROWS
getTasksQry FOUND 1 ROWS
getTasksQry FOUND 1 ROWS
There are three projects in the system.
Running your code returned the following:
getTasksQry FOUND 1 ROWS
getTasksQry FOUND 1 ROWS
getTasksQry FOUND 1 ROWS
Great - we're moving in the right direction.
Do you expect the query to find 1 row every time? If so, you might want to add LIMIT 1 to the query so the SQL engine doesn't do a table scan every time (see AntiPHPractice #26).
Next, please use print_r() to print out the rows that were found so we can see what data is in there.
Do you expect the query to find 1 row every time? If so, you might want to add LIMIT 1 to the query so the SQL engine doesn't do a table scan every time (see AntiPHPractice #26).
Next, please use print_r() to print out the rows that were found so we can see what data is in there.
ASKER
Yes, it should typically always always return one row. I will add that limit to the query.
getTasksQry FOUND 1 ROWSArray
(
[taskLength] => 2
)
getTasksQry FOUND 1 ROWSArray
(
[taskLength] => 3
)
getTasksQry FOUND 1 ROWSArray
(
[taskLength] => 63
)
Good. We know that taskLength makes sense. Next step is to repeat this pattern of data discovery on the other data elements. Run the queries, print them out and make sure every one of them is showing what you expect.
ASKER
getTasksQry FOUND 1 ROWS Last Completed Project: 2013-10-14
Project Id: 3 - 2 days - 2013-10-15 - 2013-10-17
getTasksQry FOUND 1 ROWS Last Completed Project: 2013-10-14
Project Id: 5 - 3 days - 2013-10-15 - 2013-10-18
Everything is looking good. Here is the part that needs to be changed somehow.
Project ID 3 is displaying exactly how it should.
HOWEVER, Project ID # 5 is to be completed AFTER project Id #3, but there is no logic in the code stating that these projects do not run at the same time, but instead, one after another.
The logic to make that happen is what I'm unsure of.
Yes, I'm unsure of it, too. Can you please post the script as it is now? I'll try to follow the variables. In a semi-related matter, you might want to get the assistance of a data base administrator. It might be worth rethinking the tables structure.
ASKER
foreach($programmers AS $programmer)
{
echo '<strong>' . getCkname($programmer) . ' Projects</strong><br /><br />';
//Get Projects
$getProjects = mysql_query("SELECT helpDesk_projectList.id, createdFor, projectName, projectPriority, projectStatus, programmerAssigned
FROM helpDesk_projectList
LEFT JOIN helpDesk_projectAssignments ON helpDesk_projectList.id = helpDesk_projectAssignments.projectId
WHERE (projectStatus = '1' OR projectStatus = '2' OR projectStatus = '3') and programmerAssigned = '".$programmer."'") or die("Cannot get current projects: " . mysql_error());
if(mysql_num_rows($getProjects) > 0)
{
$z = 1;
while($pData = mysql_fetch_assoc($getProjects))
{
$getTasksQry = "SELECT SUM(taskLength) as taskLength FROM helpDesk_projectTasks WHERE projectId = '{$pData["id"]}' LIMIT 1";
$getTasks = mysql_query($getTasksQry);
if (!$getTasks)
{
$err = "<br>FAIL: $getTasksQry";
$err .= "<br>ERRNO: " . mysql_errno();
$err .= "<br>ERROR: " . mysql_error();
trigger_error($err, E_USER_ERROR);
}
$numTasks = mysql_num_rows($getTasks);
while($tData = mysql_fetch_assoc($getTasks))
{
$taskLength = $tData['taskLength'];
}
$currentProject = $pData['id'];
if($z == '1')
{
//Set End Date for last completed project!
$lastCompletedProject = lastCompletedProject($programmer);
$nextStart = date("Y-m-d", strtotime($lastCompletedProject . " + 1 weekday"));
$estimatedEnd = date("Y-m-d", strtotime($nextStart . " + $taskLength weekdays"));
}
if($z > '1')
{
$lastCompletedProject = $estimatedEnd;
$nextStart = date("Y-m-d", strtotime($lastCompletedProject . " + 1 weekday"));
$estimatedEnd = date("Y-m-d", strtotime($nextStart . " + $taskLength weekdays"));
$estimatedEnd = date("Y-m-d", strtotime($estimatedEnd . " 1 weekday"));
}
echo 'Last Completed Project: ' . $lastCompletedProject . '<br /><br />';
//Print Task Length and Start & End Dates.
echo ' Project Id: ' . $pData['id'] . ' - ' . $taskLength . ' days - ' . $nextStart . ' - ' . $estimatedEnd . '<br />';
$z++;
echo '<br />';
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That certainly helps put me on the right track. Thank you. The problem is that the creator of this project doesn't want to store a lot of dates and sort of generate everything dynamically, which is what complicates this a lot.
... complicates this a lot.You can say that again! Thanks for the points and good luck with the project, ~Ray
ASKER
Thanks, I'll need it!
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_201-Handling-date-and-time-in-PHP-and-MySQL.html