EnVisageOnline/Main-RMO/Source/EnVisage/Code/BLL/MixManagers/MixModelsMergeManager.cs

422 lines
16 KiB
C#

using EnVisage.Code.DAL.Mongo;
using EnVisage.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace EnVisage.Code.BLL
{
/// <summary>
/// Does merging of client changes model to server model
/// </summary>
public class MixModelsMergeManager
{
public void MergeFilters(MixFilterModel serverModel, MixFilterModel clientModel)
{
if ((clientModel == null) || (clientModel.Selection == null))
return;
if (serverModel == null)
throw new ArgumentNullException("serverModel");
if (serverModel.Selection == null)
serverModel.Selection = new MixFilterSelectionModel();
serverModel.Selection.StartDate = clientModel.Selection.StartDate;
serverModel.Selection.EndDate = clientModel.Selection.EndDate;
serverModel.Selection.TeamsViews = clientModel.Selection.TeamsViews.Select(c => new MixTeamViewModel()
{
Id = c.Id,
IsNew = c.IsNew,
TVName = c.TVName,
Group = new SelectListGroup { Name = c.Group.Name, Disabled = false },
CompanyId = c.CompanyId,
CostCenterId = c.CostCenterId,
CapacityTeamId = c.CapacityTeamId,
CopyPlanned = c.CopyPlanned,
UserId = (c.UserId != null) ? c.UserId.Select(u => u).ToArray() : null,
Data = (c.Data != null) ? c.Data.Where(d => (d != null)).Select(r => new WidgetExpCategory()
{
Id = r.Id,
Name = r.Name,
InPlan = r.InPlan,
Positions = (r.Positions != null) ? r.Positions.Where(a => (a != null)).Select(p =>
new WidgetExpCatPosition()
{
StartDate = p.StartDate,
EndDate = p.EndDate,
Need = p.Need,
SDate = null,
EDate = null
}).ToArray() : null
}).ToArray() : null
}).ToList();
}
public void MergeHeaders(MixSaveModel serverModel, MixSaveModel clientModel)
{
serverModel.Id = clientModel.Id;
serverModel.Name = clientModel.Name;
serverModel.StartDate = clientModel.StartDate;
serverModel.EndDate = clientModel.EndDate;
serverModel.CreatedBy = clientModel.CreatedBy;
if (clientModel.Users != null)
{
if (serverModel.Users == null)
serverModel.Users = new List<Guid>();
List<Guid> usersToAppend = clientModel.Users.Where(u => !serverModel.Users.Contains(u)).ToList();
serverModel.Users.AddRange(usersToAppend);
}
}
public void MergeCalendars(MixSaveModel serverModel, MixSaveModel clientModel,
DateTime periodStartWeekending, DateTime periodEndWeekending)
{
if ((serverModel == null) || (serverModel.Calendar == null))
return;
if ((clientModel == null) || (clientModel.Calendar == null))
return;
// Convert period bound dates to Unix
long startDateUnix = GetUnixDate(periodStartWeekending);
long endDateUnix = GetUnixDate(periodEndWeekending);
this.MergeTeamCollections(serverModel.Calendar, clientModel.Calendar);
this.MergeProjectCollections(serverModel.Calendar, clientModel.Calendar);
this.SortProjects(serverModel.Calendar, startDateUnix, endDateUnix);
this.MergeProjectLists(serverModel.Calendar, clientModel.Calendar);
this.MergeLayouts(serverModel.Calendar, clientModel.Calendar);
}
protected void MergeProjectCollections(MixCalendarModel serverCalendarModel,
MixCalendarModel clientCalendarModel)
{
if (serverCalendarModel == null)
throw new ArgumentNullException("serverCalendarModel");
if (serverCalendarModel.Projects == null)
serverCalendarModel.Projects = new Dictionary<string, MixProjectModel>();
if ((clientCalendarModel == null) || (clientCalendarModel.Projects == null))
return;
// Get project list to update (exist in both models)
List<string> projectsToUpdate = serverCalendarModel.Projects.Where(p =>
clientCalendarModel.Projects.ContainsKey(p.Key)).Select(p => p.Key).ToList();
foreach (string projectId in projectsToUpdate)
{
MixProjectModel serverProjectItem = serverCalendarModel.Projects[projectId];
MixProjectModel clientProjectItem = clientCalendarModel.Projects[projectId];
MergeSingleProjectModels(serverProjectItem, clientProjectItem);
}
}
protected void MergeSingleProjectModels(MixProjectModel serverProjectModel, MixProjectModel clientProjectModel)
{
if (clientProjectModel.Scenario != null)
serverProjectModel.Scenario = clientProjectModel.Scenario.Clone();
else
serverProjectModel.Scenario = null;
if (clientProjectModel.Teams != null)
{
// Merging of project Teams
serverProjectModel.Teams = new List<Guid>();
serverProjectModel.Teams.AddRange(clientProjectModel.Teams);
}
}
protected void MergeTeamCollections(MixCalendarModel serverCalendarModel, MixCalendarModel clientCalendarModel)
{
if (serverCalendarModel.Teams == null)
throw new ArgumentNullException("serverCalendarModel.Teams");
if (clientCalendarModel.Teams == null)
return;
// Merging of teams, that exist both in server and client models
// serverModel must have all new teams from clientModel (as a result of the MixController.GetCalendar method)
foreach (MixTeamModel clientTeam in clientCalendarModel.Teams)
{
MixTeamModel serverTeam = serverCalendarModel.Teams.FirstOrDefault(t => t.Id.Equals(clientTeam.Id));
if ((serverTeam != null) && (serverTeam.Id.Length > 0))
{
MergeSingleTeamModels(serverTeam, clientTeam);
}
}
// Check, if some new teams in client Model doesn't exist in server Model.
// If so, write here code for adding absent teams
}
protected void MergeSingleTeamModels(MixTeamModel serverTeamModel, MixTeamModel clientTeamModel)
{
if (serverTeamModel == null)
throw new ArgumentNullException("serverTeamModel");
if (clientTeamModel == null)
throw new ArgumentNullException("clientTeamModel");
serverTeamModel.CompanyId = clientTeamModel.CompanyId;
serverTeamModel.CostCenterId = clientTeamModel.CostCenterId;
serverTeamModel.Name = clientTeamModel.Name;
serverTeamModel.UserId = clientTeamModel.UserId;
serverTeamModel.PlannedCapacity =
(clientTeamModel.PlannedCapacity != null) ?
clientTeamModel.PlannedCapacity.Select(pc => new MixTeamCapacity()
{
Id = pc.Id,
ExpCatId = pc.ExpCatId,
Values = (pc.Values != null) ? pc.Values.Select(k =>
new KeyValuePair<string, decimal>(k.Key, k.Value))
.ToDictionary(k => k.Key, v => v.Value) : new Dictionary<string, decimal>()
}).ToList() : null;
serverTeamModel.ExpCategories =
(clientTeamModel.ExpCategories != null) ?
clientTeamModel.ExpCategories.Select(k =>
new KeyValuePair<string, ActivityExpCategoryFooterModel>(k.Key, new ActivityExpCategoryFooterModel()
{
Id = k.Value.Id,
Name = k.Value.Name,
UomValue = k.Value.UomValue,
ActualCapacityValues = (k.Value.ActualCapacityValues != null) ?
k.Value.ActualCapacityValues.Select(ac =>
new KeyValuePair<string, decimal>(ac.Key, ac.Value))
.ToDictionary(ac => ac.Key, ac => ac.Value) : new Dictionary<string, decimal>(),
AllocatedCapacity = (k.Value.AllocatedCapacity != null) ?
k.Value.AllocatedCapacity.Select(ac =>
new KeyValuePair<string, decimal>(ac.Key, ac.Value))
.ToDictionary(ac => ac.Key, ac => ac.Value) : new Dictionary<string, decimal>(),
NeedCapacity = (k.Value.NeedCapacity != null) ?
k.Value.NeedCapacity.Select(ac =>
new KeyValuePair<string, decimal>(ac.Key, ac.Value))
.ToDictionary(ac => ac.Key, ac => ac.Value) : new Dictionary<string, decimal>(),
PlannedCapacityValues = (k.Value.PlannedCapacityValues != null) ?
k.Value.PlannedCapacityValues.Select(ac =>
new KeyValuePair<string, decimal>(ac.Key, ac.Value))
.ToDictionary(ac => ac.Key, ac => ac.Value) : new Dictionary<string, decimal>(),
Resources = (k.Value.Resources != null) ?
k.Value.Resources.Select(ac =>
new KeyValuePair<string, ActivityResourceFooterModel>(ac.Key, new ActivityResourceFooterModel()
{
Id = ac.Value.Id,
Name = ac.Value.Name,
AllocatedCapacity = (ac.Value.AllocatedCapacity != null) ?
ac.Value.AllocatedCapacity.Select(r =>
new KeyValuePair<string, decimal>(r.Key, r.Value))
.ToDictionary(r => r.Key, r => r.Value) : new Dictionary<string, decimal>(),
TotalCapacity = (ac.Value.TotalCapacity != null) ?
ac.Value.TotalCapacity.Select(r =>
new KeyValuePair<string, decimal>(r.Key, r.Value))
.ToDictionary(r => r.Key, r => r.Value) : new Dictionary<string, decimal>()
})).ToDictionary(r => r.Key, r => r.Value) : new Dictionary<string, ActivityResourceFooterModel>()
})).ToDictionary(k => k.Key, v => v.Value) : null;
}
protected void SortProjects(MixCalendarModel model, long startDateUnix, long endDateUnix)
{
model.ManagedProjects = new List<Guid>();
model.UnscheduledProjects = new List<Guid>();
model.QueuedProjects = new List<Guid>();
model.UnassignedExpendituresProjects = new List<CategoryExpenditureInProject>(); // SA. ENV-1210
if ((model.Projects == null) || (model.Projects.Count < 1))
return;
foreach (string projectIdText in model.Projects.Keys)
{
Guid projectId = new Guid(projectIdText);
MixProjectModel projectModel = model.Projects[projectIdText];
if (projectModel.Scenario == null)
{
// Send project to Unscheduled list
model.UnscheduledProjects.Add(projectId);
continue;
}
if ((projectModel.Scenario.StartDate > endDateUnix) ||
(projectModel.Scenario.EndDate < startDateUnix))
{
// Send project to Queued list
model.QueuedProjects.Add(projectId);
continue;
}
model.ManagedProjects.Add(projectId);
}
}
protected void MergeProjectLists(MixCalendarModel serverCalendarModel, MixCalendarModel clientCalendarModel)
{
if (serverCalendarModel == null)
throw new ArgumentException("serverCalendarModel");
if (serverCalendarModel.Projects == null)
throw new ArgumentException("serverCalendarModel.Projects");
if (serverCalendarModel.Teams == null)
throw new ArgumentException("serverCalendarModel.Teams");
if ((clientCalendarModel == null) || (clientCalendarModel.Projects == null))
return;
if (((clientCalendarModel.Projects == null) || (clientCalendarModel.Projects.Count < 1)) &&
(clientCalendarModel.ManagedProjects == null || (clientCalendarModel.ManagedProjects.Count < 1)) &&
((clientCalendarModel.UnscheduledProjects == null) || (clientCalendarModel.UnscheduledProjects.Count < 1)))
// Client model is empty
return;
foreach (var project in serverCalendarModel.Projects)
{
var mixProject = clientCalendarModel.Projects.FirstOrDefault(x => x.Value.Id == project.Value.Id);
if(mixProject.Value != null)
project.Value.Pinned = mixProject.Value.Pinned;
}
// Merge Managed projects lists
List<Guid> existingManagedProjects = clientCalendarModel.ManagedProjects.Where(p =>
serverCalendarModel.ManagedProjects.Contains(p)).ToList();
List<Guid> newManagedProjectsFromServer = serverCalendarModel.ManagedProjects.Where(p =>
!existingManagedProjects.Contains(p) && !clientCalendarModel.UnscheduledProjects.Contains(p)).ToList();
serverCalendarModel.ManagedProjects.RemoveAll(p => !existingManagedProjects.Contains(p));
serverCalendarModel.ManagedProjects.AddRange(newManagedProjectsFromServer);
// Merge Unscheduled projects lists
List<Guid> existingUnscheduledProjects = clientCalendarModel.UnscheduledProjects.Where(p =>
serverCalendarModel.UnscheduledProjects.Contains(p)).ToList();
List<Guid> newUnscheduledProjectsFromServer = clientCalendarModel.UnscheduledProjects.Where(p =>
!existingUnscheduledProjects.Contains(p) &&
!serverCalendarModel.ManagedProjects.Contains(p)).ToList();
serverCalendarModel.UnscheduledProjects.RemoveAll(p => !existingUnscheduledProjects.Contains(p));
serverCalendarModel.UnscheduledProjects.AddRange(newUnscheduledProjectsFromServer);
serverCalendarModel.QueuedProjects.RemoveAll(p => serverCalendarModel.ManagedProjects.Contains(p) ||
serverCalendarModel.UnscheduledProjects.Contains(p));
// Merge Unassigned Expenditures Projects lists (ENV-1210)
List<CategoryExpenditureInProject> existingUnassignedExpProjects = clientCalendarModel.UnassignedExpendituresProjects.Where(p =>
serverCalendarModel.Projects.ContainsKey(p.ProjectId.ToString())).ToList();
serverCalendarModel.UnassignedExpendituresProjects.Clear();
serverCalendarModel.UnassignedExpendituresProjects.AddRange(existingUnassignedExpProjects);
}
protected void MergeLayouts(MixCalendarModel serverCalendarModel, MixCalendarModel clientCalendarModel)
{
if (serverCalendarModel == null)
throw new ArgumentException("serverCalendarModel");
if (serverCalendarModel.Projects == null)
throw new ArgumentException("serverCalendarModel.Projects");
if (serverCalendarModel.Teams == null)
throw new ArgumentException("serverCalendarModel.Teams");
if ((clientCalendarModel == null) || (clientCalendarModel.Projects == null) ||
(clientCalendarModel.Layout == null) || (clientCalendarModel.Layout.Count < 1))
return;
List<Guid> layoutTeams = serverCalendarModel.Teams.Select(t => new Guid(t.Id)).ToList();
serverCalendarModel.Layout = new List<MixTeamLayoutRowItem>();
foreach (Guid teamId in layoutTeams)
{
List<Guid> existingForTeam = serverCalendarModel.ManagedProjects.Where(p =>
(serverCalendarModel.Projects[p.ToString()].Teams != null) &&
(serverCalendarModel.Projects[p.ToString()].Teams.Contains(teamId)) &&
(clientCalendarModel.Layout != null) &&
clientCalendarModel.Layout.Any(l => (l.TeamId.Equals(teamId) && l.ProjectId.Equals(p)))
).ToList();
List<Guid> newForTeam = serverCalendarModel.ManagedProjects.Where(p =>
(serverCalendarModel.Projects[p.ToString()].Teams != null) &&
(serverCalendarModel.Projects[p.ToString()].Teams.Contains(teamId)) &&
!existingForTeam.Contains(p)
).ToList();
List<MixTeamLayoutRowItem> teamLayoutRowsForExisingProjects =
clientCalendarModel.Layout.Where(l => l.TeamId.Equals(teamId) && existingForTeam.Contains(l.ProjectId))
.Select(r => new MixTeamLayoutRowItem()
{
TeamId = teamId,
Row = r.Row,
ProjectId = r.ProjectId,
Index = r.Index
}).OrderBy(o1 => o1.Row).ThenBy(o2 => o2.Index).ToList();
List<MixTeamLayoutRowItem> teamLayoutRowsForNewProjects =
newForTeam.Select(pId => new MixTeamLayoutRowItem()
{
TeamId = teamId,
Row = -1,
ProjectId = pId,
Index = 0
}).ToList();
// Renum row numbers for result layout rows
int lastOldRowNum = -1;
int newRowNum = -1;
int newColNum = 0;
foreach (MixTeamLayoutRowItem currentLayoutRow in teamLayoutRowsForExisingProjects)
{
if (lastOldRowNum != currentLayoutRow.Row)
{
// Project is located at new line
lastOldRowNum = currentLayoutRow.Row;
newRowNum++;
newColNum = 0;
}
else
{
// Projects is located at the same line with the previous one
newColNum++;
}
currentLayoutRow.Row = newRowNum;
currentLayoutRow.Index = newColNum;
}
// Set row numbers for new project layout rows
foreach (MixTeamLayoutRowItem currentLayoutRow in teamLayoutRowsForNewProjects)
{
newRowNum++;
currentLayoutRow.Row = newRowNum;
currentLayoutRow.Index = 0;
}
serverCalendarModel.Layout.AddRange(teamLayoutRowsForExisingProjects);
serverCalendarModel.Layout.AddRange(teamLayoutRowsForNewProjects);
}
}
protected long GetUnixDate(DateTime? date)
{
return date.HasValue ? Utils.ConvertToUnixDate(date.Value) : 0;
}
}
}