using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Web; using EnVisage.Models; namespace EnVisage.Code.BLL { public class ProjectManager : ManagerBase { public ProjectManager(EnVisageEntities dbContext) : base(dbContext) { } protected override Project InitInstance() { return new Project { Id = Guid.NewGuid() }; } protected override Project RetrieveReadOnlyById(Guid key) { return DataTable.AsNoTracking().FirstOrDefault(t => t.Id == key); } public override DbSet DataTable { get { return DbContext.Projects; } } public override Project Save(ProjectModel model) { if (model == null) throw new ArgumentNullException("model"); var partManager = new ProjectPartManager(DbContext); if (!model.HasChildren && model.Parts.Count == 1) { var part = model.Parts[0]; model.StatusId = part.StatusId; model.TypeId = part.TypeId; model.ClientId = part.ClientId; model.Details = part.Details; model.Priority = part.Priority; model.IsRevenueGenerating = part.IsRevenueGenerating; model.Deadline = part.Deadline; model.Probability = part.Probability; model.ParentProjectId = null; model.ExternalContacts = part.ExternalContacts; model.InternalContacts = part.InternalContacts; model.AssignedTeams = part.AssignedTeams; } else if (model.HasChildren && model.Parts.Count > 0) { model.StatusId = model.Parts[0].StatusId; model.TypeId = model.Parts[0].TypeId; model.ClientId = model.Parts[0].ClientId; } var obj = base.Save(model); if (model.HasChildren && model.Parts.Count > 0) { var currentParts = model.Id == Guid.Empty ? new List() : DbContext.Projects.Where(t => t.ParentProjectId == model.Id).ToList(); for (var i=0; i < model.Parts.Count; i++) { var projectModel = model.Parts[i]; if (projectModel.DeletedPart && projectModel.Id != Guid.Empty) { var item2Delete = currentParts.FirstOrDefault(t => t.Id == projectModel.Id); if (item2Delete !=null) DbContext.Entry(item2Delete).State = EntityState.Deleted; } else if (currentParts.All(t => t.Id != projectModel.Id)) { projectModel.ParentProjectId = obj.Id; projectModel.SaveAsCopy = model.SaveAsCopy; var oldId = model.Parts[i].OldId; model.Parts[i] = (ProjectPartModel)partManager.Save(projectModel); model.Parts[i].OldId = oldId; } else { var oldId = model.Parts[i].OldId; projectModel.SaveAsCopy = model.SaveAsCopy; model.Parts[i] = (ProjectPartModel)partManager.Save(projectModel); model.Parts[i].OldId = oldId; } } } if (!model.HasChildren && model.Parts.Count == 1) { #region save project contacts if (model.ExternalContacts == null) model.ExternalContacts = new List(); if (model.InternalContacts == null) model.InternalContacts = new List(); var allCurrentContacts = model.ExternalContacts.Concat(model.InternalContacts).ToList(); var oldContacts = DbContext.Contact2Project.Where(c2S => c2S.ShowId == obj.Id).ToList(); foreach (var c in oldContacts) { if (allCurrentContacts.Contains(c.ContactId)) allCurrentContacts.Remove(c.ContactId); else DbContext.Contact2Project.Remove(c); } foreach (var cId in allCurrentContacts) { DbContext.Contact2Project.Add(new Contact2Project() { Id = Guid.NewGuid(), ContactId = cId, ShowId = obj.Id, Contact = DbContext.Contacts.FirstOrDefault(c=>c.Id == cId) }); } #endregion #region save project teams if (model.AssignedTeams == null) model.AssignedTeams = new List(); var oldTeams = DbContext.Team2Project.Where(x => x.ProjectId == obj.Id).ToList(); if (model.Id != Guid.Empty) { var oldTeamIds = oldTeams.Select(x => x.TeamId).ToList(); var oldTeamsUsers = DbContext.User2Team.Where(x => oldTeamIds.Contains(x.TeamId)).Select(x => x.UserId.ToLower()).Distinct().ToList(); var newTeamsUsers = DbContext.User2Team.Where(x => model.AssignedTeams.Contains(x.TeamId)).Select(x => x.UserId.ToLower()).Distinct().ToList(); var projectUsers = DbContext.ProjectAccesses.Where(x => x.ProjectId == obj.Id).Select(x => x.PrincipalId.ToString().ToLower()).ToList(); var usersToRemove = (from c in oldTeamsUsers where !newTeamsUsers.Contains(c) select c).ToList(); var usersToAdd = (from c in newTeamsUsers where !projectUsers.Contains(c) select c).ToList(); foreach (var user in usersToAdd) { DbContext.ProjectAccesses.Add(new ProjectAccess() { PrincipalId = new Guid(user), ProjectId = obj.Id, Read = 1, Write = 1 }); } DbContext.ProjectAccesses.RemoveRange(DbContext.ProjectAccesses.Where(x => x.ProjectId == obj.Id && usersToRemove.Contains(x.PrincipalId.ToString())).ToList()); } foreach (var t in oldTeams) { if (model.AssignedTeams.Contains(t.TeamId)) model.AssignedTeams.Remove(t.TeamId); else { DbContext.Team2Project.Remove(t); } } foreach (var tId in model.AssignedTeams) { DbContext.Team2Project.Add(new Team2Project() { Id = Guid.NewGuid(), ProjectId = obj.Id, TeamId = tId }); } #endregion } return obj; } } public class ProjectPartManager : ManagerBase { public ProjectPartManager(EnVisageEntities dbContext) : base(dbContext) { } protected override Project InitInstance() { return new Project { Id = Guid.NewGuid() }; } protected override Project RetrieveReadOnlyById(Guid key) { return DataTable.AsNoTracking().FirstOrDefault(t => t.Id == key); } public override DbSet DataTable { get { return DbContext.Projects; } } public override Project Save(ProjectPartModel model) { var obj = base.Save(model); #region save project contacts if (model.ExternalContacts == null) model.ExternalContacts = new List(); if (model.InternalContacts == null) model.InternalContacts = new List(); var allCurrentContacts = model.ExternalContacts.Concat(model.InternalContacts).ToList(); var oldContacts = DbContext.Contact2Project.Where(c2S => c2S.ShowId == obj.Id).ToList(); foreach (var c in oldContacts) { if (allCurrentContacts.Contains(c.ContactId)) allCurrentContacts.Remove(c.ContactId); else DbContext.Contact2Project.Remove(c); } foreach (var cId in allCurrentContacts) { DbContext.Contact2Project.Add(new Contact2Project() { Id = Guid.NewGuid(), ContactId = cId, ShowId = obj.Id, Contact = DbContext.Contacts.FirstOrDefault(c => c.Id == cId) }); } #endregion #region save project teams if (model.AssignedTeams == null) model.AssignedTeams = new List(); var oldTeams = DbContext.Team2Project.Where(x => x.ProjectId == obj.Id).ToList(); if (model.Id != Guid.Empty) { var oldTeamIds = oldTeams.Select(x => x.TeamId).ToList(); var oldTeamsUsers = DbContext.User2Team.Where(x => oldTeamIds.Contains(x.TeamId)).Select(x => x.UserId.ToLower()).Distinct().ToList(); var newTeamsUsers = DbContext.User2Team.Where(x => model.AssignedTeams.Contains(x.TeamId)).Select(x => x.UserId.ToLower()).Distinct().ToList(); var projectUsers = DbContext.ProjectAccesses.Where(x => x.ProjectId == obj.Id).Select(x => x.PrincipalId.ToString().ToLower()).ToList(); var usersToRemove = (from c in oldTeamsUsers where !newTeamsUsers.Contains(c) select c).ToList(); var usersToAdd = (from c in newTeamsUsers where !projectUsers.Contains(c) select c).ToList(); foreach (var user in usersToAdd) { DbContext.ProjectAccesses.Add(new ProjectAccess() { PrincipalId = new Guid(user), ProjectId = obj.Id, Read = 1, Write = 1 }); } DbContext.ProjectAccesses.RemoveRange(DbContext.ProjectAccesses.Where(x => x.ProjectId == obj.Id && usersToRemove.Contains(x.PrincipalId.ToString())).ToList()); } foreach (var t in oldTeams) { if (model.AssignedTeams.Contains(t.TeamId)) model.AssignedTeams.Remove(t.TeamId); else { DbContext.Team2Project.Remove(t); } } foreach (var tId in model.AssignedTeams) { DbContext.Team2Project.Add(new Team2Project() { Id = Guid.NewGuid(), ProjectId = obj.Id, TeamId = tId }); } #endregion if (model.Id == Guid.Empty) { #region Create Actuals scenario if (!model.SaveAsCopy) { var scenario = new Scenario { Id = Guid.NewGuid(), Name = "ACTUALS", ParentId = obj.Id, Type = ScenarioType.Actuals.GetHashCode(), StartDate = DateTime.Now, Color = "", ProjectedRevenue = 0 }; DbContext.Scenarios.Add(scenario); } #endregion #region Copy scenarios and referenced scenario details if (model.SaveAsCopy) { var oldId = Guid.Empty; var scenarios = DbContext.Scenarios.Where(t => t.ParentId == oldId).ToList(); foreach (var currScenario in scenarios) { var currDetails = DbContext.ScenarioDetail.Where( t => t.ParentID == currScenario.Id).AsNoTracking().ToList().OrderBy(t => t.ExpenditureCategoryId).ThenBy(t => t.WeekOrdinal); var newScenario = new Scenario { Id = Guid.NewGuid(), ParentId = obj.Id, Type = currScenario.Type, Name = currScenario.Name, ProjectedRevenue = currScenario.ProjectedRevenue, ExpectedGrossMargin = currScenario.ExpectedGrossMargin, CalculatedGrossMargin = currScenario.CalculatedGrossMargin, CGSplit = currScenario.CGSplit, EFXSplit = currScenario.EFXSplit, Duration = currScenario.Duration, TDDirectCosts = currScenario.TDDirectCosts, BUDirectCosts = currScenario.BUDirectCosts, Shots = currScenario.Shots, TDRevenueShot = currScenario.TDRevenueShot, BURevenueShot = currScenario.BURevenueShot, LastUpdate = DateTime.Now, Status = currScenario.Status, UseLMMargin = currScenario.UseLMMargin, ExpectedGrossMargin_LM = currScenario.ExpectedGrossMargin_LM, CalculatedGrossMargin_LM = currScenario.CalculatedGrossMargin_LM, TDDirectCosts_LM = currScenario.TDDirectCosts_LM, BUDirectCosts_LM = currScenario.BUDirectCosts_LM, BURevenueShot_LM = currScenario.BURevenueShot_LM, EntryTimeStamp = DateTime.Now, Actuals_BUDirectCosts = currScenario.Actuals_BUDirectCosts, Actuals_BUDirectCosts_LM = currScenario.Actuals_BUDirectCosts_LM, FreezeRevenue = currScenario.FreezeRevenue, GrowthScenario = currScenario.GrowthScenario, TemplateId = currScenario.TemplateId, Color = currScenario.Color, ProjectedExpense = currScenario.ProjectedExpense, StartDate = currScenario.StartDate, EndDate = currScenario.EndDate, ShotStartDate = currScenario.ShotStartDate, SystemAttributeObjectID = currScenario.SystemAttributeObjectID }; DbContext.Scenarios.Add(newScenario); foreach (var detail in currDetails) { var newDetailItem = new ScenarioDetail { Id = Guid.NewGuid(), ExpenditureCategoryId = detail.ExpenditureCategoryId, ParentID = newScenario.Id, Quantity = detail.Quantity, Cost = detail.Cost, WeekOrdinal = detail.WeekOrdinal, WeekEndingDate = detail.WeekEndingDate, LastUpdate = DateTime.Now }; DbContext.ScenarioDetail.Add(newDetailItem); } } } #endregion } return obj; } } }