For tasks without recourse the start and end dates are not calculated correctly when using the Recalculate method.
Here is sample C # code (attached Project1.mpp):
[TestMethod]
public void Incorrect_Dates_After_Import()
{
using (var destinationStream = ProjetoPadrao.Carregar())
{
var destination = new Project(destinationStream);
using (var originStream = File.Open(@"C:\Aspose - Bugs\Project1.mpp", FileMode.Open))
{
var origin = new Project(originStream);
destination.CalculationMode = CalculationMode.None;
ImportResources(origin, destination);
ImportRootTask(origin, destination);
ImportTasks(origin.RootTask.Children, destination);
var destnationTasks = new List<Task>();
GetAllTasks(destination.RootTask, destnationTasks);
var links = origin.TaskLinks;
foreach (var link in links)
{
var predTaskOrigin = link.PredTask;
var succTaskOrigin = link.SuccTask;
if (predTaskOrigin != null && succTaskOrigin != null && !succTaskOrigin.Children.Any())
{
var predTask = destnationTasks.SingleOrDefault(t => t.Get(Tsk.Id) == predTaskOrigin.Get(Tsk.Id));
var succTask = destnationTasks.SingleOrDefault(t => t.Get(Tsk.Id) == succTaskOrigin.Get(Tsk.Id));
var duration = destination.GetDuration(link.LinkLag, link.LagFormat);
if (predTask != null && succTask != null)
{
var taskLink = destination.TaskLinks.Add(predTask, succTask, link.LinkType, destination.GetDuration(link.LinkLag / 10, TimeUnitType.Minute).Convert(link.LagFormat));
taskLink.LagFormat = link.LagFormat;
}
}
}
var tasksBeforeRecalculate = destination.TaskLinks.Where(t => t.SuccTask.Get(Tsk.Start) <= t.SuccTask.Get(Tsk.Finish));
Assert.IsTrue(tasksBeforeRecalculate.Count() == destination.TaskLinks.Count);
destination.Recalculate();
var tasksAfterRecalculate = destination.TaskLinks.Where(t => t.SuccTask.Get(Tsk.Start) <= t.SuccTask.Get(Tsk.Finish));
Assert.IsTrue(tasksBeforeRecalculate.Count() == destination.TaskLinks.Count);
}
}
}
private static IEnumerable<Task> GetAllTasks(Task parentTask, List<Task> list)
{
foreach (var task in parentTask.Children)
{
list.Add(task);
GetAllTasks(task, list);
}
return list;
}
private void ImportResources(Project origin, Project destination)
{
foreach (var resource in origin.Resources)
destination.Resources.Add(resource.Get(Rsc.Name));
}
private void ImportTasks(IEnumerable<Task> tasks, Project destination)
{
foreach (var task in tasks)
{
var newTask = destination.RootTask.Children.Add(task.Get(Tsk.Name));
destination.RootTask.Children.Add(CloneTask(task, newTask, destination));
if (task.Children.Any())
ImportChildrenOfATask(task.Children, newTask, destination);
}
}
private void ImportChildrenOfATask(TaskCollection children, Task task, Project project)
{
foreach (var child in children)
{
Task newChild = task.Children.Add(child.Get(Tsk.Name));
task.Children.Add(CloneTask(child, newChild, project));
if (child.Children.Any())
ImportChildrenOfATask(child.Children, newChild, project);
}
}
private void ImportRootTask(Project origin, Project destination)
{
CloneTask(origin.RootTask, destination.RootTask, destination);
}
private Task CloneTask(Task origin, Task destination, Project project)
{
if (!origin.Children.Any())
{
foreach (var assignment in origin.Assignments)
{
var resource = assignment.Get(Asn.Resource);
if (resource != null)
{
var resourceName = String.IsNullOrEmpty(resource.Get(Rsc.Name)) ? $"{Siteware.Resources.Resource.Recurso + " " + resource.Get(Rsc.Uid)}" : resource.Get(Rsc.Name);
var res = project.Resources.SingleOrDefault(r => r.Get(Rsc.Id) == resource.Get(Rsc.Id));
res.Set(Rsc.Name, resourceName);
var newAssignment = project.ResourceAssignments.Add(destination, res, assignment.Get(Asn.Units));
newAssignment.Set(Asn.Work, assignment.Get(Asn.Work));
}
}
destination.Set(Tsk.Duration, origin.Get(Tsk.Duration));
destination.Set(Tsk.DurationFormat, TimeUnitType.Day);
SetWork(destination, destination.Get(Tsk.Work).ToDouble(), TimeUnitType.Hour);
}
destination.Set(Tsk.Start, origin.Get(Tsk.Start).Date);
destination.Set(Tsk.Finish, origin.Get(Tsk.Finish).Date);
destination.Set(Tsk.Id, origin.Get(Tsk.Id));
destination.Set(Tsk.OutlineLevel, origin.Get(Tsk.OutlineLevel));
destination.Set(Tsk.IsMilestone, origin.Get(Tsk.IsMilestone));
SetWork(destination, destination.Get(Tsk.Work).ToDouble(), TimeUnitType.Hour);
DateTime? constraintDate = origin.Get(Tsk.ConstraintDate).Date;
var constraintType = origin.Get(Tsk.ConstraintType);
constraintDate = ReturnConstraintDate(constraintType, origin.Get(Tsk.ConstraintDate).Date, project);
destination.Set(Tsk.ConstraintType, constraintType);
if (constraintDate.HasValue)
destination.Set(Tsk.ConstraintDate, constraintDate.Value);
return destination;
}
private DateTime? ReturnConstraintDate(ConstraintType constraintType, DateTime constraintDate, Project project)
{
if (constraintDate == DateTime.MinValue)
return null;
var calendar = project.Calendars.First();
var startHour = TimeSpan.FromHours(calendar.GetWorkingTimes(DateTime.UtcNow).First().FromTime.Hour);
var finishHour = TimeSpan.FromHours(calendar.GetWorkingTimes(DateTime.UtcNow).LastOrDefault().ToTime.Hour);
switch (constraintType)
{
case ConstraintType.AsLateAsPossible: { constraintDate = constraintDate.Date + startHour; break; }
case ConstraintType.AsSoonAsPossible: { constraintDate = constraintDate.Date + startHour; break; }
case ConstraintType.FinishNoEarlierThan: { constraintDate = constraintDate.Date + finishHour; break; }
case ConstraintType.FinishNoLaterThan: { constraintDate = constraintDate.Date + finishHour; break; }
case ConstraintType.MustFinishOn: { constraintDate = constraintDate.Date + finishHour; break; }
case ConstraintType.MustStartOn: { constraintDate = constraintDate.Date + startHour; break; }
case ConstraintType.StartNoEarlierThan: { constraintDate = constraintDate.Date + startHour; break; }
case ConstraintType.StartNoLaterThan: { constraintDate = constraintDate.Date + startHour; break; }
}
return constraintDate;
}
private Task SetWork(Task task, double value, TimeUnitType timeUnit)
{
var duration = task.ParentProject.GetDuration(value, timeUnit).Convert(TimeUnitType.Hour);
task.Set(Tsk.Work, duration);
return task;
}
This Topic is created by kashif.iqbal using the Email to Eopic plugin.