using System.Collections.Specialized; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Net; using System.Web.Routing; using EnVisage.App_Start; using EnVisage.Code.BLL; using EnVisage.Code.Cache; using EnVisage.Code.HtmlHelpers; using EnVisage.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using jQuery.DataTables.Mvc; using EnVisage.Code; using Microsoft.AspNet.Identity; namespace EnVisage.Controllers { [Authorize] public class ScenariosController : BaseController { // GET: /Scenarios/Templates [HttpGet] [AreaSecurityAttribute(area = Areas.ScenarioTemplates, level = AccessLevel.Read)] public ActionResult Templates() { if (!HtmlHelpers.CheckSecurityObjectPermission(null, Areas.ScenarioTemplates, AccessLevel.Read)) return Redirect("/"); return View(); } [HttpGet] //[ValidateAntiForgeryToken] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult LoadScenario(Guid? Id) { //if (Id.HasValue) { CreateScenarioModel model = new CreateScenarioModel(); model.ScenarioId = Guid.Empty; model.TemplateId = Guid.Empty; model.Project = DbContext.Projects.AsNoTracking().FirstOrDefault(p => p.Id == Id); model.ProjectDeadline = model.Project.Deadline; var TeamAllocations = model.Project.Team2Project.ToDictionary(c => c.TeamId, c => (double)100 / model.Project.Team2Project.Count()); model.TeamAllocations = Newtonsoft.Json.JsonConvert.SerializeObject(TeamAllocations); if (model.Project.ParentProjectId.HasValue) { model.ProjectId = model.Project.ParentProjectId.Value; model.PartId = Id; } else { model.ProjectId = Id.Value; } return PartialView("_createScenario", model); } } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public JsonResult UpdateTeamsAllocation(ScenarioDetailModel model) { var projman = new ProjectManager(DbContext); var project = projman.Load(model.ParentId); var ProjTeamIds = project.Team2Project.Select(x => x.TeamId).ToList(); var teamallocations = Newtonsoft.Json.JsonConvert.DeserializeObject>(model.TeamAllocationsJson); var MissingTeams = teamallocations.Keys.Where(x => !ProjTeamIds.Contains(x)).ToList(); var OtherScenarios = project.Scenarios.ToList(); DbContext.Team2Scenario.RemoveRange(DbContext.Team2Scenario.Where(x => x.ScenarioId == model.Id).ToList()); DbContext.SaveChanges(); foreach (var teamalloc in teamallocations) { var newTA = new Team2Scenario(); newTA.Id = Guid.NewGuid(); newTA.ScenarioId = model.Id; newTA.TeamId = teamalloc.Key; newTA.Allocation = teamalloc.Value; DbContext.Team2Scenario.Add(newTA); } foreach (var team in MissingTeams) { var newTP = new Team2Project(); newTP.Id = Guid.NewGuid(); newTP.ProjectId = model.ParentId; newTP.TeamId = team; DbContext.Team2Project.Add(newTP); foreach (var scen in OtherScenarios) { if (scen.Id == model.Id) continue; var newTA = new Team2Scenario(); newTA.Id = Guid.NewGuid(); newTA.ScenarioId = scen.Id; newTA.TeamId = team; newTA.Allocation = 0; DbContext.Team2Scenario.Add(newTA); } } DbContext.SaveChanges(); return Json("ok", JsonRequestBehavior.AllowGet); } [HttpPost] [ValidateAntiForgeryToken] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult CreateScenario(CreateScenarioModel model, Guid[] expCatId, string[] expCatName, string[] expCatGroup, bool[] expCatChecked) { //if (model == null || ContentLocker.IsLock("Trainings", model.Id.ToString(), User.Identity.Name)) // return new HttpStatusCodeResult(HttpStatusCode.BadRequest); try { model.TrimStringProperties(); var costSavingItems = string.IsNullOrEmpty(model.CostSavingItems) ? new List() : Newtonsoft.Json.JsonConvert.DeserializeObject> (model.CostSavingItems) ?? new List(); if (ModelState.IsValid) { var projman = new ProjectManager(DbContext); var project = projman.Load(model.PartId ?? model.ProjectId); model.IsRevenueGenerating = project.IsRevenueGenerating; model.Project = project; if (expCatId != null && expCatName != null && expCatGroup != null && expCatChecked != null && expCatId.Length == expCatName.Length && expCatId.Length == expCatGroup.Length && expCatId.Length == expCatChecked.Length) { model.ScenarioExpenditures = new ScenarioModel.ExpenditureItem[expCatId.Length]; for (var i = 0; i < expCatId.Length; i++) { model.ScenarioExpenditures[i] = new ScenarioModel.ExpenditureItem { Id = expCatId[i], Group = expCatGroup[i], Name = expCatName[i], Checked = expCatChecked[i] }; } } model.ProjectDeadline = project.Deadline; var ProjTeamIds = model.Project.Team2Project.Select(x => x.TeamId).ToList(); var teamallocations = Newtonsoft.Json.JsonConvert.DeserializeObject>(model.TeamAllocations); var MissingTeams = teamallocations.Keys.Where(x => !ProjTeamIds.Contains(x)).ToList(); var OtherScenarios = model.Project.Scenarios.ToList(); var manager = new ScenarioManager(DbContext); var dbObj = manager.Save((ScenarioModel) model); if (!model.SaveAsDraft) { foreach (var teamalloc in teamallocations) { var newTA = new Team2Scenario(); newTA.Id = Guid.NewGuid(); newTA.ScenarioId = dbObj.Id; newTA.TeamId = teamalloc.Key; newTA.Allocation = teamalloc.Value; DbContext.Team2Scenario.Add(newTA); } foreach (var team in MissingTeams) { var newTP = new Team2Project(); newTP.Id = Guid.NewGuid(); newTP.ProjectId = model.ProjectId; newTP.TeamId = team; DbContext.Team2Project.Add(newTP); foreach (var scen in OtherScenarios) { if (scen.Id == dbObj.Id) continue; var newTA = new Team2Scenario(); newTA.Id = Guid.NewGuid(); newTA.ScenarioId = scen.Id; newTA.TeamId = team; newTA.Allocation = 0; DbContext.Team2Scenario.Add(newTA); } } foreach (var scenarioCostSavingModel in costSavingItems) { for (var month = 1; month < scenarioCostSavingModel.Costs.Length; month++) { if (scenarioCostSavingModel.Costs[month].HasValue) DbContext.CostSavings.Add(new CostSaving { Id = Guid.NewGuid(), Cost = scenarioCostSavingModel.Costs[month].Value, Month = (short) month, Year = scenarioCostSavingModel.Year, ScenarioId = dbObj.Id }); } } DbContext.SaveChanges(); } //ContentLocker.RemoveLock("Trainings", model.Id.ToString(), User.Identity.Name); model.Project = DbContext.Projects.AsNoTracking().FirstOrDefault(p => p.Id == model.ProjectId); return new HttpStatusCodeResult(HttpStatusCode.OK); //PartialView("_createScenario", model); } } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot save expenditure categoies. Try again later."); } } catch (Exception exception) // handle any unexpected error { LogException(exception); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot save expenditure categoies. Try again later."); } HttpContext.Response.StatusCode = 500; HttpContext.Response.Clear(); //return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri); model.Project = DbContext.Projects.AsNoTracking().FirstOrDefault(p => p.Id == model.ProjectId); return PartialView("_createScenario", model); } [HttpGet] //[ValidateAntiForgeryToken] [AreaSecurityAttribute(area = Areas.Trainings, level = AccessLevel.Write)] public ActionResult GetECsByTemplateId(Guid? Id) { var manager = new ScenarioManager(DbContext); var ec = manager.GetExpenditureCategories(Id); return PartialView("_createScenarioExpenditures", ec); } [HttpGet] //[ValidateAntiForgeryToken] [AreaSecurityAttribute(area = Areas.Trainings, level = AccessLevel.Write)] public ActionResult GetProjectPartsByProjectId(Guid? Id) { var pp = Utils.GetProjectParts(Id); return PartialView("_createScenarioProjectParts", pp); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult ProcessRates(RatesModel model) { try { model.TrimStringProperties(); switch (model.Mode) { case RatesModel.FormMode.ListRates: #region List Rates model.EditRateId = Guid.Empty; model.DeleteRateId = Guid.Empty; if (!Guid.Empty.Equals(model.ExpenditureCategoryId)) { var gRates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.Type == (int) RateModel.RateType.Global select c); model.AddGlobalRange(gRates.ToList()); } if (Guid.Empty != model.ScenarioId && !Guid.Empty.Equals(model.ExpenditureCategoryId)) { var lRates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.Type == (int) RateModel.RateType.Derived && c.ParentId == model.ScenarioId select c); model.AddLocalRange(lRates.ToList()); } #endregion break; case RatesModel.FormMode.EditRate: #region Load Edit Rate Form if (model.EditRateId.HasValue && !Guid.Empty.Equals(model.EditRateId)) { var rate = DbContext.Rates.AsNoTracking().FirstOrDefault(t => t.Id == model.EditRateId); if (rate != null) { model.EditRate = new RateModel() { Id = rate.Id, DerivedObjectId = rate.DerivedId, EndDate = rate.EndDate, ExpenditureCategoryId = rate.ExpenditureCategoryId, FreezeRate = rate.FreezeRate, ParentId = rate.ParentId, Rate1 = rate.Rate1, StartDate = rate.StartDate, Type = (RateModel.RateType) rate.Type }; } } else { model.EditRate = new RateModel() { DerivedObjectId = Guid.Empty, EndDate = new DateTime(9999, 12, 31), ExpenditureCategoryId = model.ExpenditureCategoryId, FreezeRate = 0, ParentId = model.ScenarioId, Rate1 = 0, StartDate = new DateTime(1753, 1, 1), Type = RateModel.RateType.Derived }; } #endregion break; case RatesModel.FormMode.ConfirmEditRate: #region Save Rate if (ModelState.IsValid) { if (ContentLocker.IsLock("ExpenditureCategoryRate", model.EditRateId.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); var manager = new RateManager(DbContext); manager.Save(model.EditRate); DbContext.SaveChanges(); manager.Dispose(); ContentLocker.RemoveLock("ExpenditureCategoryRate", model.EditRateId.ToString(), User.Identity.Name); model.Mode = RatesModel.FormMode.ListRates; // reset action mode model.EditRateId = Guid.Empty; model.DeleteRateId = Guid.Empty; if (!Guid.Empty.Equals(model.ExpenditureCategoryId)) { var gRates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.Type == (int) RateModel.RateType.Global select c); model.AddGlobalRange(gRates.ToList()); } if (Guid.Empty != model.ScenarioId && !Guid.Empty.Equals(model.ExpenditureCategoryId)) { var lRates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.Type == (int) RateModel.RateType.Derived && c.ParentId == model.ScenarioId select c); model.AddLocalRange(lRates.ToList()); } } else { model.Mode = RatesModel.FormMode.EditRate; HttpContext.Response.StatusCode = 500; HttpContext.Response.Clear(); } #endregion break; case RatesModel.FormMode.DeriveRate: #region Derive rate from global var sManager = new ScenarioManager(DbContext); var scenario = sManager.Load(model.ScenarioId); if (!Guid.Empty.Equals(model.ExpenditureCategoryId) && !Guid.Empty.Equals(model.ScenarioId)) { var rates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.Type == (int) RateModel.RateType.Global && c.StartDate <= scenario.EndDate && c.EndDate >= scenario.StartDate select c).ToList(); foreach (var rate in rates) { var derivedrates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.ParentId == model.ScenarioId && c.DerivedId == rate.Id select c).ToList(); DbContext.Rates.RemoveRange(derivedrates); var newrate = new Rate { Id = Guid.NewGuid(), Rate1 = rate.Rate1, StartDate = (rate.StartDate < scenario.StartDate) ? scenario.StartDate.Value : rate.StartDate, EndDate = (rate.EndDate > scenario.EndDate) ? scenario.EndDate.Value : rate.EndDate, ExpenditureCategoryId = rate.ExpenditureCategoryId, FreezeRate = rate.FreezeRate, ParentId = model.ScenarioId, Type = (short) RateModel.RateType.Derived, DerivedId = rate.Id }; DbContext.Rates.Add(newrate); DbContext.SaveChanges(); } } model.Mode = RatesModel.FormMode.ListRates; // reset action mode model.EditRateId = Guid.Empty; model.DeleteRateId = Guid.Empty; if (!Guid.Empty.Equals(model.ExpenditureCategoryId)) { var gRates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.Type == (int) RateModel.RateType.Global select c); model.AddGlobalRange(gRates.ToList()); } if (Guid.Empty != model.ScenarioId && !Guid.Empty.Equals(model.ExpenditureCategoryId)) { var lRates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.Type == (int) RateModel.RateType.Derived && c.ParentId == model.ScenarioId select c); model.AddLocalRange(lRates.ToList()); } #endregion break; case RatesModel.FormMode.ConfirmDeleteRate: #region delete rate if (!Guid.Empty.Equals(model.ExpenditureCategoryId) && !Guid.Empty.Equals(model.ScenarioId)) { var deleterates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.ParentId == model.ScenarioId select c); if (model.DeleteRateId != null && !Guid.Empty.Equals(model.DeleteRateId)) deleterates = deleterates.Where(t => t.Id == model.DeleteRateId); DbContext.Rates.RemoveRange(deleterates); DbContext.SaveChanges(); } model.DeleteRateId = Guid.Empty; model.EditRateId = Guid.Empty; model.Mode = RatesModel.FormMode.ListRates; // reset action mode if (!Guid.Empty.Equals(model.ExpenditureCategoryId)) { var gRates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.Type == (int) RateModel.RateType.Global select c); model.AddGlobalRange(gRates.ToList()); } if (Guid.Empty != model.ScenarioId && !Guid.Empty.Equals(model.ExpenditureCategoryId)) { var lRates = (from c in DbContext.Rates where c.ExpenditureCategoryId == model.ExpenditureCategoryId && c.Type == (int) RateModel.RateType.Derived && c.ParentId == model.ScenarioId select c); model.AddLocalRange(lRates.ToList()); } break; #endregion } return PartialView("_rates", model); } catch (BLLException blEx) { if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } model.Mode = RatesModel.FormMode.EditRate; } catch (Exception exception) { LogException(exception); SetErrorScript(); model.Mode = RatesModel.FormMode.EditRate; } if (ModelState.IsValid && (RatesModel.FormMode.ConfirmEditRate == model.Mode || RatesModel.FormMode.ConfirmDeleteRate == model.Mode) && Guid.Empty != model.EditRateId) ContentLocker.RemoveLock("ExpenditureCategoryRate", model.EditRateId.ToString(), User.Identity.Name); HttpContext.Response.StatusCode = 500; HttpContext.Response.Clear(); return PartialView("_rates", model); } /// /// Returns JSON UnitOfMeasure list with filters and sort for jQuery DataTables /// [HttpPost] [AreaSecurityAttribute(area = Areas.ScenarioTemplates, level = AccessLevel.Read)] public JsonResult Templates(JQueryDataTablesModel jQueryDataTablesModel) { int totalRecordCount; int searchRecordCount; var units = GetTemplates(startIndex: jQueryDataTablesModel.iDisplayStart, pageSize: jQueryDataTablesModel.iDisplayLength, sortedColumns: jQueryDataTablesModel.GetSortedColumns(), totalRecordCount: out totalRecordCount, searchRecordCount: out searchRecordCount, searchString: jQueryDataTablesModel.sSearch); return this.DataTablesJson(items: units, totalRecords: totalRecordCount, totalDisplayRecords: searchRecordCount, sEcho: jQueryDataTablesModel.sEcho); } private IEnumerable GetTemplates(int startIndex, int pageSize, IEnumerable sortedColumns, out int totalRecordCount, out int searchRecordCount, string searchString) { var query = from c in DbContext.Scenarios where c.Type == (int)ScenarioType.Template select new ScenarioListItemModel { Id = c.Id, Name = c.Name, StartDate = c.StartDate, EndDate = c.EndDate, Duration = c.Duration, CGSplit = c.CGSplit, EFXSplit = c.EFXSplit, ScenariosCount = c.ChildScenarios.Count()}; //filter if (!string.IsNullOrWhiteSpace(searchString)) { query = query.Where(c => c.Name.ToLower().Contains(searchString.ToLower())); } //sort foreach (var sortedColumn in sortedColumns) { switch (sortedColumn.PropertyName) { case "Id": if (sortedColumn.Direction == SortingDirection.Ascending) query = query.OrderBy(c => c.Id); else query = query.OrderByDescending(c => c.Id); break; case "StartDate": if (sortedColumn.Direction == SortingDirection.Ascending) query = query.OrderBy(c => c.StartDate); else query = query.OrderByDescending(c => c.StartDate); break; case "EndDate": if (sortedColumn.Direction == SortingDirection.Ascending) query = query.OrderBy(c => c.EndDate); else query = query.OrderByDescending(c => c.EndDate); break; case "Duration": if (sortedColumn.Direction == SortingDirection.Ascending) query = query.OrderBy(c => c.Duration); else query = query.OrderByDescending(c => c.Duration); break; case "CGSplit": if (sortedColumn.Direction == SortingDirection.Ascending) query = query.OrderBy(c => c.CGSplit); else query = query.OrderByDescending(c => c.CGSplit); break; case "EFXSplit": if (sortedColumn.Direction == SortingDirection.Ascending) query = query.OrderBy(c => c.EFXSplit); else query = query.OrderByDescending(c => c.EFXSplit); break; case "ScenariosCount": if (sortedColumn.Direction == SortingDirection.Ascending) query = query.OrderBy(c => c.ScenariosCount); else query = query.OrderByDescending(c => c.ScenariosCount); break; default: if (sortedColumn.Direction == SortingDirection.Ascending) query = query.OrderBy(c => c.Name); else query = query.OrderByDescending(c => c.Name); break; } } totalRecordCount = DbContext.Scenarios.Count(s => s.Type == (int?)ScenarioType.Template); searchRecordCount = query.Count(); return query.Skip(startIndex).Take(pageSize).ToList(); } // GET: /Scenarios/ [HttpGet] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Read)] public ActionResult Index() { return View(); } // GET: /Scenarios/ [HttpGet] public ActionResult LoadExpenditures(Guid? id) { if (id == null || id == Guid.Empty) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); try { var manager = new ScenarioManager(DbContext); var model = manager.GetExpenditureCategories(id.Value); return PartialView("_expenditures", model); } catch (BLLException blEx) { if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } } catch (Exception exception) { LogException(exception); SetErrorScript(); } return PartialView("_expenditures", new List()); } // GET: /Scenarios/Edit/5 [HttpGet] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult Edit(Guid? id, Guid? parentId, string backUrl, string backName) { if ((id == null || id == Guid.Empty) && (parentId == null || parentId == Guid.Empty)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); var model = new ScenarioModel(); try { var manager = new ScenarioManager(DbContext); model = (ScenarioModel)manager.Load(id) ?? new ScenarioModel(); if (model.Id == Guid.Empty) // create new scenario { model.LaborSplitPercentage = 100; //model.StartDate = DateTime.Today; //model.EndDate = DateTime.Today.AddYears(1); //model.MilestoneStartDate = DateTime.Today; model.UseActuals = true; model.IsActiveScenario = true; model.TotalMilestones = 1; model.GrossMargin = 0; model.LMMargin = 0; var project = DbContext.Projects.FirstOrDefault(x => x.Id == parentId); if (project != null) { model.IsRevenueGenerating = project.IsRevenueGenerating; } var initialTemplate = Utils.GetScenarioTemplates().FirstOrDefault(); if (initialTemplate != null) { var items = manager.GetExpenditureCategories(new Guid(initialTemplate.Value)); if (items != null) model.Expenditures = items; } if (!model.IsRevenueGenerating) { model.ProjectedRevenue = 0; } } else // edit scenario { model.PriorWeekCutOff = DateTime.Today; if (!model.MilestoneStartDate.HasValue || model.MilestoneStartDate.Value == Constants.ProjectionsDefaultDate) model.MilestoneStartDate = model.StartDate; model.UseActuals = !model.GrowthScenario; var items = manager.GetExpenditureCategories(model.Id); if (items != null) model.Expenditures = items; } if (model.UseLMMargin) { model.GrossMargin = null; } else { model.LMMargin = null; } if (model.Id == Guid.Empty && parentId != null) model.ParentId = parentId.Value; model.BackUrl = backUrl; model.BackName = backName; } catch (BLLException blEx) { if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } } catch (Exception exception) { LogException(exception); SetErrorScript(); } return View(model); } [HttpPost] //[ValidateAntiForgeryToken] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult ChangeExpenditures(ScenarioDetailModel model, Guid[] expCatId, string[] expCatName, string[] expCatGroup, bool[] expCatChecked) { List expCatList = new List(); for (var i = 0; i < expCatId.Length; i++) { if (expCatChecked.Length > i && expCatChecked[i] && expCatName.Length > i) { expCatList.Add(new ExpenditureModel() { Id = expCatId[i], Name = expCatName[i] }); } } var manager = new ScenarioManager(DbContext); ModelState.Clear(); if (model != null && model.Id != Guid.Empty) { try { manager.SaveExpenditureCategories(model.Id, expCatList); return JavaScript("window.location.search += '&tab=scenarios';"); //return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot save expedenture categoies. Try again later."); } } catch (Exception exception) // handle any unexpected error { LogException(exception); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot save expedenture categoies. Try again later."); } } HttpContext.Response.StatusCode = 500; HttpContext.Response.Clear(); model.ScenarioExpenditures = manager.GetExpenditureCategories(model.Id); model.ScenarioExpenditures.Where(x => expCatList.Select(ec => ec.Id).Contains(x.Id)).ToList().ForEach(x => x.Checked = true); return PartialView("_expendituresModal", model); } // POST: /Scenarios/Edit/5 // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult Edit(ScenarioModel model, Guid[] expCatId, string[] expCatName, string[] expCatGroup, bool[] expCatChecked) { if (model.Id != Guid.Empty && ContentLocker.IsLock("Scenario", model.Id.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); //if (model.Id == Guid.Empty) model.Id = Guid.NewGuid(); model.TrimStringProperties(); if (!model.AsDraft && expCatChecked.All(c => c == false)) ModelState.AddModelError("ExpenditureCategoriesEmpty",string.Format(Constants.ERROR_ONE_OR_MORE_SELECTED_ELEMENTS_REQUIRED, "Expenditure Categories")); if (expCatId != null && expCatName != null && expCatGroup != null && expCatChecked != null && expCatId.Length == expCatName.Length && expCatId.Length == expCatGroup.Length && expCatId.Length == expCatChecked.Length) { model.Expenditures = new ScenarioModel.ExpenditureItem[expCatId.Length]; for (var i = 0; i < expCatId.Length; i++) { model.Expenditures[i] = new ScenarioModel.ExpenditureItem { Id = expCatId[i], Group = expCatGroup[i], Name = expCatName[i], Checked = expCatChecked[i] }; } } if (ModelState.IsValid) { try { var manager = new ScenarioManager(DbContext); var scenario = manager.Save(model); if (model.Id != Guid.Empty) ContentLocker.RemoveLock("Scenario", model.Id.ToString(), User.Identity.Name); return RedirectToAction("Details", "Scenarios", new { id = scenario.Id, backUrl = model.BackUrl, backName = model.BackName }); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); SetErrorScript(); } } catch (Exception exception) // handle any unexpected error { LogException(exception); SetErrorScript(); } } // return empty model with validation messages (if any) string url = Request.QueryString["ref"]; if (!string.IsNullOrEmpty(url)) return Redirect(url); return View(model); } [HttpPost] public ActionResult LoadScenarioCalendar(ScenarioDetailsModel model, Guid[] expCatId, bool[] expCatChecked) { if (ModelState.IsValid) { try { model = GetScenarioCalendar(model); return Json(model); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); SetErrorScript(); } } catch (Exception exception) // handle any unexpected error { LogException(exception); SetErrorScript(); } } return PartialView("_scenarioCalendar", model); } [HttpPost] public ActionResult LoadJsonScenarioCalendar(ScenarioDetailsModel model) { if (model == null || model.ScenarioId == Guid.Empty) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); var scenario = DbContext.Scenarios.AsNoTracking().FirstOrDefault(t => t.Id == model.ScenarioId); if (scenario == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); model.StartDate = scenario.StartDate ?? DateTime.Today; model.EndDate = scenario.EndDate ?? DateTime.Today.AddYears(1); model.GrowthScenario = scenario.GrowthScenario; model.ScenarioId = scenario.Id; model.ParentId = scenario.ParentId ?? Guid.Empty; model.ScenarioType = (ScenarioType?) scenario.Type; return Json(GetScenarioCalendar(model), JsonRequestBehavior.AllowGet); } private class Pairs { public Guid Id { get; set; } public decimal Quantity { get; set; } } private ScenarioDetailsModel GetScenarioCalendar(ScenarioDetailsModel model) { DateTime periodStartDate; DateTime periodEndDate; DateTime? actualsEndDate; Guid actualScenarioId = Guid.Empty; var allExpCats = DbContext.ExpenditureCategory.AsNoTracking().ToList(); var allUoms = DbContext.UOMs.AsNoTracking().ToList(); if (!model.IsUOMHours.HasValue) { var user = new UsersCache().Value.FirstOrDefault(x => x.Id == new Guid(HttpContext.User.Identity.GetUserId())); if (user != null) model.IsUOMHours = !user.PreferredResourceAllocation; } switch (model.ScenarioType) { case ScenarioType.LoanOut: case ScenarioType.Training: case ScenarioType.Vacation: periodStartDate = new DateTime(DateTime.Today.Year, 1, 1); periodEndDate = new DateTime(DateTime.Today.Year, 12, 31); break; case ScenarioType.Actuals: periodStartDate = model.StartDate; periodEndDate = model.EndDate; break; default: periodStartDate = model.StartDate; periodEndDate = model.EndDate; break; } if (!model.GrowthScenario && !ScenarioType.Actuals.Equals(model.ScenarioType)) { var actualScenario = DbContext.Scenarios.FirstOrDefault( t => t.ParentId == model.ParentId && t.Type == (int?) ScenarioType.Actuals); if (actualScenario != null) { actualScenarioId = actualScenario.Id; actualsEndDate = actualScenario.EndDate; if (actualScenario.StartDate < model.StartDate) periodStartDate = actualScenario.StartDate ?? new DateTime(1900, 1, 1); if (actualScenario.EndDate > model.EndDate) periodEndDate = actualScenario.EndDate ?? new DateTime(1900, 1, 1); } else actualsEndDate = new DateTime(1900, 1, 1); } else actualsEndDate = new DateTime(1900, 1, 1); var scenarioDetailsQuery = DbContext.VW_ScenarioAndProxyDetails.AsNoTracking() .Where(t => t.ParentID == model.ScenarioId && t.WeekEndingDate >= periodStartDate && t.WeekEndingDate <= periodEndDate); if (model.CreditDepartment != null) scenarioDetailsQuery = scenarioDetailsQuery.Where(t => t.CreditId == model.CreditDepartment); if (model.GLAccount != null) scenarioDetailsQuery = scenarioDetailsQuery.Where(t => t.GLId == model.GLAccount); if (model.LaborMaterials != null) scenarioDetailsQuery = scenarioDetailsQuery.Where(t => t.CGEFX == model.LaborMaterials.ToString()); if (model.CategoryType != null) scenarioDetailsQuery = scenarioDetailsQuery.Where(t => t.Type == (int?)model.CategoryType); if (model.IncomeType != null) scenarioDetailsQuery = scenarioDetailsQuery.Where(t => t.SystemAttributeOne == model.IncomeType); var checkedExpCats = model.SelectedExpCats ?? new List(); if (checkedExpCats.Count > 0) scenarioDetailsQuery = scenarioDetailsQuery.Where(t => checkedExpCats.Contains(t.ExpenditureCategoryId.Value)); scenarioDetailsQuery = scenarioDetailsQuery.OrderBy(t => t.ExpenditureCategoryName).ThenBy(t => t.WeekEndingDate); var scenarioDetails = scenarioDetailsQuery.Select(t => new { t.Id, t.ExpenditureCategoryId, t.WeekEndingDate, t.GLId, t.ExpenditureCategoryName, t.Quantity, t.Cost, t.ParentID, t.WeekOrdinal, t.UseType, t.UOMId }).ToArray().GroupBy( key => new { key.ExpenditureCategoryId, key.ExpenditureCategoryName, key.ParentID, key.GLId, key.UseType, key.UOMId }).ToDictionary(key => key.Key, grouping => grouping.ToList()); var totalRow = new ScenarioDetailsModel.ScenarioCalendarRow { ExpCatId = Guid.Empty, ExpCatName = "Totals", GrandTotalCost = 0, GrandTotalQuantity = 0, UseType = ExpenditureCategoryModel.UseTypes.Calculated }; var scenarioCalendarGrid = new List { // create a scenario calendar row for column totals totalRow }; if (scenarioDetails.Count > 0) { BuildHeaders(model, scenarioDetails.FirstOrDefault().Value.Select(t => t.WeekEndingDate ?? DateTime.MinValue).Distinct().OrderBy(o => o).ToList()); totalRow.ScenarioDetailIds = new Guid?[model.Headers.Count]; totalRow.CostValues = new decimal[model.Headers.Count]; totalRow.QuantityValues = new decimal[model.Headers.Count]; //var expenditureCategoryIds = scenarioDetails.Where(x=>x.Key.ExpenditureCategoryId.HasValue).Select(x=>x.Key.ExpenditureCategoryId.Value).Distinct().ToList(); model.AllResources = new List(); var resourcesByTeams = DbContext.Team2Project.Where(x => x.ProjectId == model.ParentId).Select(x => x.Team.PeopleResources); foreach(var teamResource in resourcesByTeams) { model.AllResources.AddRange(teamResource.Select(x => new ScenarioDetailsModel.ScenarioCalendarRowResource() { Id = x.Id, Name = x.FirstName + " " + x.LastName, ExpedentureCategoryId = x.ExpenditureCategoryId, IsActiveEmployee = x.IsActiveEmployee })); } var allResIds = model.AllResources.Select(t => t.Id).Distinct().ToArray(); var allResourceVacations = DbContext.PeopleResourceVacations.Where(t => allResIds.Contains(t.PeopleResourceId)).Select(t => new { t.PeopleResourceId, t.HoursOff, t.WeekEndingDate }).ToArray(); var allResourceTrainings = DbContext.PeopleResourceTrainings.Where(t => allResIds.Contains(t.PeopleResourceId)).Select(t => new { t.PeopleResourceId, t.HoursOff, t.WeekEndingDate }).ToArray(); var resourceAllocation = DbContext.PeopleResourceAllocations.Where(r => r.ScenarioId == model.ScenarioId).ToList(); foreach (var row in scenarioDetails) { var expCatRow = new ScenarioDetailsModel.ScenarioCalendarRow { ExpCatId = row.Key.ExpenditureCategoryId ?? Guid.Empty, ExpCatName = row.Key.ExpenditureCategoryName, GrandTotalCost = 0, GrandTotalQuantity = 0, ScenarioDetailIds = new Guid?[model.Headers.Count], CostValues = new decimal[model.Headers.Count], QuantityValues = new decimal[model.Headers.Count], UseType = (ExpenditureCategoryModel.UseTypes)row.Key.UseType, Resources = model.AllResources.Where(x => resourceAllocation.Where(ec=>ec.ExpenditureCategoryId == row.Key.ExpenditureCategoryId ). Select(r=>r.PeopleResourceId).Contains( x.Id)). Select(x=> new ScenarioDetailsModel.ScenarioCalendarRowResource() {Id = x.Id, Name = x.Name, QuantityValues = new decimal[model.Headers.Count], CostValues = new decimal[model.Headers.Count], CapacityQuantityValues = new decimal[model.Headers.Count], }).ToList(), RestQuantity = new decimal[model.Headers.Count], RestCost = new decimal[model.Headers.Count] }; var uomMultiplier = Utils.GetUOMMultiplier(allExpCats, allUoms, row.Key.ExpenditureCategoryId ?? Guid.Empty, model.IsUOMHours); var uomValue = allUoms.FirstOrDefault(t => t.Id == row.Key.UOMId); var colIndex = 0; var monthCost = 0.0M; var monthQuantity = 0.0M; var resourceTotals = model.AllResources.Select(x => new Pairs() { Id = x.Id, Quantity = 0.0M }).ToList(); foreach (var column in row.Value) { expCatRow.ScenarioDetailIds[colIndex] = column.Id; expCatRow.CostValues[colIndex] = column.Cost ?? 0; expCatRow.QuantityValues[colIndex] = (column.Quantity ?? 0)*uomMultiplier; expCatRow.GrandTotalCost += (column.Cost ?? 0); expCatRow.GrandTotalQuantity += (column.Quantity ?? 0) * uomMultiplier; //Get resources cost\quantity var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); var date = epoch.AddSeconds(model.Headers[colIndex].Milliseconds / 1000); var currAllocation = resourceAllocation.Where(r => r.WeekEndingDate == date && r.ExpenditureCategoryId == column.ExpenditureCategoryId).ToList(); //expCatRow.Resources.ForEach(x => x.CostValues[colIndex] = (currAllocation != null ? (decimal)currAllocation.AllocatePercentage * (column.Cost ?? 0) : 0)); //expCatRow.Resources.ForEach(x => x.GrandTotalCost += (currAllocation != null ? (decimal)currAllocation.AllocatePercentage * (column.Cost ?? 0) : 0)); expCatRow.Resources.ForEach(x => { // set resource weekly allocation x.QuantityValues[colIndex] = (currAllocation.FirstOrDefault(ar => ar.PeopleResourceId == x.Id) != null ? (decimal) (currAllocation.FirstOrDefault(ar => ar.PeopleResourceId == x.Id).Quantity ?? 0) : 0)*uomMultiplier; // set resource weekly availability (UOM.Value - vacations - loan offs - trainings) if (uomValue != null) { var vacationsSum = allResourceVacations.Where(t => t.PeopleResourceId == x.Id && t.WeekEndingDate <= date && t.WeekEndingDate >= date.AddDays(-6)) .Sum(s => s.HoursOff); var trainingsSum = allResourceTrainings.Where(t => t.PeopleResourceId == x.Id && t.WeekEndingDate <= date && t.WeekEndingDate >= date.AddDays(-6)) .Sum(s => s.HoursOff); x.CapacityQuantityValues[colIndex] = (uomValue.UOMValue - vacationsSum - trainingsSum) * uomMultiplier; } }); expCatRow.Resources.ForEach(x => x.GrandTotalQuantity += (currAllocation.FirstOrDefault(ar => ar.PeopleResourceId == x.Id) != null ? (decimal)(currAllocation.FirstOrDefault(ar => ar.PeopleResourceId == x.Id).Quantity ?? 0) : 0) * uomMultiplier); expCatRow.RestQuantity[colIndex] = expCatRow.QuantityValues[colIndex] - expCatRow.Resources.Select(x => x.QuantityValues[colIndex]).Sum() * uomMultiplier; //expCatRow.RestCost[colIndex] = expCatRow.CostValues[colIndex] - expCatRow.Resources.Select(x => x.CostValues[colIndex]).Sum(); totalRow.CostValues[colIndex] += expCatRow.CostValues[colIndex]; totalRow.QuantityValues[colIndex] += expCatRow.QuantityValues[colIndex]; expCatRow.Resources.ForEach(x => resourceTotals.FirstOrDefault(r => r.Id == x.Id).Quantity += x.QuantityValues[colIndex]); if (colIndex < model.Headers.Count - 1) colIndex++; monthQuantity += (column.Quantity ?? 0.0M) * uomMultiplier; monthCost += column.Cost ?? 0.0M; if (colIndex >= model.Headers.Count - 1 || model.Headers[colIndex].IsMonth) { expCatRow.ScenarioDetailIds[colIndex] = Guid.Empty; expCatRow.CostValues[colIndex] = monthCost; expCatRow.QuantityValues[colIndex] = monthQuantity; totalRow.ScenarioDetailIds[colIndex] = Guid.Empty; totalRow.CostValues[colIndex] += monthCost; totalRow.QuantityValues[colIndex] += monthQuantity; expCatRow.Resources.ForEach(x => x.QuantityValues[colIndex] = resourceTotals.FirstOrDefault(r => r.Id == x.Id).Quantity); if (colIndex < model.Headers.Count - 1) colIndex++; monthCost = 0.0M; monthQuantity = 0.0M; resourceTotals.ForEach(x=>x.Quantity = 0.0M); } } scenarioCalendarGrid.Add(expCatRow); totalRow.GrandTotalCost += expCatRow.GrandTotalCost; totalRow.GrandTotalQuantity += expCatRow.GrandTotalQuantity; } } model.ScenarioCalendar = scenarioCalendarGrid; model.ActualsEndDateMs = (long)(actualsEndDate == null ? 0 : actualsEndDate.Value.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds); return model; } public void BuildHeaders(ScenarioDetailsModel model, List gridHeaders) { model.Headers = new List((int)(gridHeaders.Count * 1.25)); var prevMonth = string.Empty; var monthIndex = -1; ScenarioDetailsModel.Header monthColumn = null; foreach (var gridHeader in gridHeaders) { // get week start date as previous week end date + 1 day //var weekStartDate = prevWeek.AddDays(1); // if there is a gap between weeks (e.g. there is a non-working week that was not represented in scenario details records) // then we should subtract 6 days from current week end date //if (gridHeader.AddDays(-6) > weekStartDate) // weekStartDate = gridHeader.AddDays(-6); // get month name as month of the week start date var gridHeaderTitle = gridHeader.ToString("MMMM yyyy"); if (!prevMonth.Equals(gridHeaderTitle)) { if (monthColumn != null) { model.Headers.Add(monthColumn); } monthColumn = new ScenarioDetailsModel.Header() { Show = true, Milliseconds = (long)gridHeader.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds, MonthIndex = ++monthIndex, IsMonth = true, Title = gridHeaderTitle, Weeks = new List() }; } var weekHeader = new ScenarioDetailsModel.Header() { IsMonth = false, Milliseconds = (long)gridHeader.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds, MonthIndex = monthColumn.MonthIndex, Title = gridHeader.ToShortDateString() }; model.Headers.Add(weekHeader); monthColumn.Weeks.Add(model.Headers.Count - 1); monthColumn.Milliseconds = weekHeader.Milliseconds; prevMonth = gridHeaderTitle; } if (monthColumn != null) { model.Headers.Add(monthColumn); } } // GET: /Scenarios/Details/5 [HttpGet] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult Details(Guid? id, string tab, string backUrl, string backName) { if (id == null || id == Guid.Empty) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); var model = new ScenarioDetailModel {ActiveTab = tab}; try { var manager = new ScenarioManager(DbContext); model = (ScenarioDetailModel)manager.Load(id) ?? new ScenarioDetailModel(); if (model.Id == Guid.Empty) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } if (model.Status == null || model.Status == ScenarioStatus.Draft) { return RedirectToAction("Edit", "Scenarios", new {id, @backUrl = backUrl ?? Url.Action("Index", "Project"), @backName = backName ?? "projects"}); } model.Expenditures = Utils.GetScenarioExpenditures(model.Id); model.Projects = Utils.GetScenarioProjects(model.Id); model.ScenarioExpenditures = manager.GetExpenditureCategories(model.Id); model.ActiveTab = tab; model.BackUrl = string.IsNullOrEmpty(backUrl) ? Request.QueryString["ref"] : backUrl; model.BackName = string.IsNullOrEmpty(backName) ? Request.QueryString["back"] : backName; model.LaborMaterialsSplit = Utils.GetLaborMaterialsSplit(model.Id); var user = new UsersCache().Value.FirstOrDefault(x => x.Id == new Guid(HttpContext.User.Identity.GetUserId())); if (user != null) ViewBag.IsUOMHours = !user.PreferredResourceAllocation; } catch (BLLException blEx) { if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } } catch (Exception exception) { LogException(exception); SetErrorScript(); } return View("Details", model); } // POST: /Scenarios/Details/5 // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult Details(ScenarioDetailModel model) { if (model.Id != Guid.Empty && ContentLocker.IsLock("Scenario", model.Id.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); model.TrimStringProperties(); try { var manager = new ScenarioManager(DbContext); manager.Save(model); if (model.Id != Guid.Empty) ContentLocker.RemoveLock("Scenario", model.Id.ToString(), User.Identity.Name); if (!string.IsNullOrEmpty(model.BackUrl)) return Redirect(model.BackUrl); else return Details(model.Id, model.ActiveTab, model.BackUrl, model.BackName); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); SetErrorScript(); } } catch (Exception exception) // handle any unexpected error { LogException(exception); SetErrorScript(); } // return empty model with validation messages (if any) if (!string.IsNullOrEmpty(model.BackUrl)) return Redirect(model.BackUrl); return View(model); } [HttpGet] public ActionResult GetScenarioAvailableExpCategories(Guid id) { var availableExpenditures = DbContext.VW_ExpCategoriesInScenario.AsNoTracking() .Where(t => t.ScenarioID == id) .OrderBy(t => t.Name) .Select(t => new {t.Id, t.Name}) .ToArray(); return Json(availableExpenditures, JsonRequestBehavior.AllowGet); } [HttpPost] public ActionResult GetRates(Guid scenarioId, bool? uomMode) { var allExpCats = DbContext.ExpenditureCategory.AsNoTracking().ToList(); var allUoms = DbContext.UOMs.AsNoTracking().ToList(); if (!uomMode.HasValue) { var user = new UsersCache().Value.FirstOrDefault(x => x.Id == new Guid(HttpContext.User.Identity.GetUserId())); if (user != null) uomMode = !user.PreferredResourceAllocation; } #region loading rates // retrieve all local rates for the specified scenario var localRates = DbContext.Rates.Where(t => t.ParentId == scenarioId && t.Type == (int) RateModel.RateType.Derived && t.ExpenditureCategoryId != null) .Select(t => new { t.ExpenditureCategoryId, t.EndDate, t.Rate1 }).OrderBy(t => t.ExpenditureCategoryId) .ThenBy(t => t.EndDate).ToArray(); // group rates by expenditure category id and store them as disctionary by expenditure category id var localRatesLu = localRates.GroupBy(t => t.ExpenditureCategoryId) .ToDictionary(key => key.Key, group => group.ToList()); // retrieve similar dictionary for global rates that does not referenced to already retrieved expenditures var globalRatesQuery = DbContext.Rates.Where(t => t.Type == (int)RateModel.RateType.Global); //TODO: we should validate SQL query to make sure it is correct and optimal if (localRates.Length > 0) globalRatesQuery = globalRatesQuery.Where(t => !localRatesLu.Keys.ToList().Contains(t.ExpenditureCategoryId)); var globalRates = globalRatesQuery .Select(t => new { t.ExpenditureCategoryId, t.EndDate, t.Rate1 }) .OrderBy(t => t.ExpenditureCategoryId).ThenBy(t => t.EndDate) .ToArray() .GroupBy(t => t.ExpenditureCategoryId) .ToDictionary(key => key.Key, group => group.ToList()); // append global rates to local rates foreach (var globalRate in globalRates) { if (localRatesLu.ContainsKey(globalRate.Key)) throw new BLLException("Unable to add global rate to the list because it already contains a local rate with the same key"); localRatesLu.Add(globalRate.Key, globalRate.Value); } #endregion return Json(localRatesLu.Select(t=> new { expCatId = t.Key, rateValues = t.Value.Select(rate => new { weekEndDate = (long)(rate.EndDate).Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds, rateValue = rate.Rate1 / Utils.GetUOMMultiplier(allExpCats, allUoms, t.Key, uomMode) }) })); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult CopyTo(ScenarioDetailModel model, Guid? Id, Guid[] projId, string[] projName, bool[] projChecked, ScenarioStatus copyStatus) { ModelState.Clear(); var checkedProject = Guid.Empty; for (var i = 0; i < projChecked.Length; i++) { if (projChecked[i] && ((projId.Length - 1) >= i)) { checkedProject = projId[i]; break; } } if (Guid.Empty.Equals( checkedProject) || !Id.HasValue) ModelState.AddModelError(string.Empty, "Invalid parameters"); else { EnVisageEntities context = new EnVisageEntities(); try { new ScenarioManager(DbContext).CopyTo(Id.Value, checkedProject, copyStatus); var detailsGrid = "[]"; return Json(detailsGrid); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); SetErrorScript(); } } catch (Exception exception) // handle any unexpected error { LogException(exception); SetErrorScript(); } } //} HttpContext.Response.StatusCode = 500; HttpContext.Response.Clear(); model.Projects = Utils.GetScenarioProjects(model.Id); return PartialView("_copyToModal", model); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult SaveChanges(SaveScenarioDetailsChangesModel model) { var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); if (model.ScenarioId != Guid.Empty && ContentLocker.IsLock("Scenario", model.ScenarioId.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); var context = new EnVisageEntities(); model.TrimStringProperties(); var allExpCats = DbContext.ExpenditureCategory.AsNoTracking().ToList(); var allUoms = DbContext.UOMs.AsNoTracking().ToList(); if (!model.ScenarioFilters.IsUOMHours.HasValue) { var user = new UsersCache().Value.FirstOrDefault(x => x.Id == new Guid(HttpContext.User.Identity.GetUserId())); if (user != null) model.ScenarioFilters.IsUOMHours = !user.PreferredResourceAllocation; } if (ModelState.IsValid) { try { var manager = new ScenarioManager(context); var scenario = manager.Load(model.ScenarioId, false); var scenarioStartDateMsSince1970 = scenario.StartDate.HasValue ? (long)scenario.StartDate.Value.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds : (long)new DateTime(1970, 1, 1).Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds; foreach (var changedExpCat in model.ChangedExpCats) { var uomMultiplier = Utils.GetUOMMultiplier(allExpCats, allUoms, changedExpCat.Id, model.ScenarioFilters.IsUOMHours); foreach (var changedColumn in changedExpCat.Values) { if (changedColumn.Milliseconds >= scenarioStartDateMsSince1970) { var scenarioDetailsItem = (from c in context.ScenarioDetail where c.Id == changedColumn.Id select c).FirstOrDefault();//manager.LoadScenarioDetail(changedColumn.Id, false); if (scenarioDetailsItem == null) continue; if ( scenarioDetailsItem.Id == Guid.Empty) { throw new NullReferenceException(string.Format("Scenario Details {0} mising", changedColumn.Id)); } scenarioDetailsItem.Quantity = changedColumn.Quantity / uomMultiplier; scenarioDetailsItem.Cost = changedColumn.Cost; } } if (changedExpCat.Resources != null){ var resourceIds = changedExpCat.Resources.Select(x=>x.Id).ToList(); var resourceAllocations = context.PeopleResourceAllocations.Where(x => resourceIds.Contains(x.PeopleResourceId) && x.ScenarioId == model.ScenarioId).ToList(); foreach (var resource in changedExpCat.Resources) { var resourceId = resource.Id; if (resource.IsRemoved) { var recourcesToDelete = context.PeopleResourceAllocations.Where(x => x.PeopleResourceId == resourceId && x.ScenarioId == model.ScenarioId).ToList(); recourcesToDelete.ForEach(x => context.PeopleResourceAllocations.Remove(x)); recourcesToDelete.ForEach(x => context.Entry(x).State = EntityState.Deleted); } else { foreach (var changedResource in resource.Values) { var date = epoch.AddSeconds(changedResource.Milliseconds/1000); var allocatedResource = (from c in resourceAllocations where c.WeekEndingDate == date && c.ScenarioId == model.ScenarioId && c.PeopleResourceId == resourceId && c.ExpenditureCategoryId == changedExpCat.Id select c).FirstOrDefault(); if (changedResource.Quantity <= 0) { if (allocatedResource != null) context.Entry(allocatedResource).State = EntityState.Deleted; continue; } if (allocatedResource == null) { allocatedResource = context.PeopleResourceAllocations.Create(); allocatedResource.Id = Guid.NewGuid(); allocatedResource.ExpenditureCategoryId = changedExpCat.Id; allocatedResource.PeopleResourceId = resourceId; allocatedResource.ScenarioId = model.ScenarioId; allocatedResource.WeekEndingDate = date; context.Entry(allocatedResource).State = EntityState.Added; } else { context.Entry(allocatedResource).State = EntityState.Modified; } allocatedResource.Quantity = changedResource.Quantity / uomMultiplier; } } } } } //TODO: review that we really need 2 transactions here. Looks like it was here since bottom-up costs recalculation was in stored procedure. context.SaveChanges(); manager.SetBottomUpCosts(scenario); context.SaveChanges(); model.ScenarioFilters.StartDate = scenario.StartDate ?? DateTime.Today; model.ScenarioFilters.EndDate = scenario.EndDate ?? DateTime.Today.AddYears(1); model.ScenarioFilters.GrowthScenario = scenario.GrowthScenario; model.ScenarioFilters.ParentId = scenario.ParentId ?? Guid.Empty; model.ScenarioFilters.ScenarioType = (ScenarioType?)scenario.Type; //var detailsGrid = GetScenarioCalendar(model.ScenarioFilters); return new HttpStatusCodeResult(HttpStatusCode.OK); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); SetErrorScript(); } } catch (Exception exception) // handle any unexpected error { LogException(exception); SetErrorScript(); } } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult AddNote(NoteModel model) { //if (model.ScenarioId != Guid.Empty && ContentLocker.IsLock("Scenario", model.ScenarioId.ToString(), User.Identity.Name)) // return new HttpStatusCodeResult(HttpStatusCode.BadRequest); model.TrimStringProperties(); if (ModelState.IsValid) { try { model.Id = Guid.NewGuid(); var newnote = new Note(); model.CopyTo(newnote); newnote.UserId = new Guid(User.Identity.GetUserId()); DbContext.Notes.Add(newnote); DbContext.SaveChanges(); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); SetErrorScript(); } } catch (Exception exception) // handle any unexpected error { LogException(exception); SetErrorScript(); } } return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult EditNote(NoteModel model) { //if (model.ScenarioId != Guid.Empty && ContentLocker.IsLock("Scenario", model.ScenarioId.ToString(), User.Identity.Name)) // return new HttpStatusCodeResult(HttpStatusCode.BadRequest); model.TrimStringProperties(); if (ModelState.IsValid) { try { var note = (from c in DbContext.Notes where c.Id == model.Id select c).FirstOrDefault(); if (note == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); note.Title = model.Title; note.NoteDetail = model.Details; DbContext.SaveChanges(); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); SetErrorScript(); } } catch (Exception exception) // handle any unexpected error { LogException(exception); SetErrorScript(); } } return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri); } // GET: /User/Edit/5 [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult DeleteNote(string Id) { if (string.IsNullOrEmpty(Id) || Id == "JSVar") { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var NoteId = new Guid(Id); var note = (from c in DbContext.Notes where c.Id == NoteId select c).FirstOrDefault(); if (note == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); else { DbContext.Notes.Remove(note); DbContext.SaveChanges(); } return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri); } // GET: /User/Edit/5 [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult EditNote(string Id) { if (string.IsNullOrEmpty(Id) || Id == "JSVar") { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var NoteId = new Guid(Id); var note = (from c in DbContext.Notes where c.Id == NoteId select c).FirstOrDefault(); if (note == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); else { return PartialView("_addNote", (NoteModel)note); } } // GET: /User/Edit/5 [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult AddNote(string Id) { if (string.IsNullOrEmpty(Id)) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var ParentId = new Guid(Id); return PartialView("_addNote", new NoteModel(ParentId)); } [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult EditRate(Guid? id, Guid? parentId, Guid expentureCategoryId) { RateModel model = null; if (id.HasValue && id != Guid.Empty) { var manager = new RateManager(DbContext); model = (RateModel)manager.Load(id); } else { var sManager = new ScenarioManager(DbContext); var scenario = sManager.Load(parentId); model = new RateModel(); model.Type = RateModel.RateType.Derived; var lRates = (from c in DbContext.Rates where c.ExpenditureCategoryId == expentureCategoryId && c.Type == (int)RateModel.RateType.Derived && c.ParentId == parentId select c).ToList(); if ((from d in lRates select d.EndDate).Max() < DateTime.MaxValue.AddYears(-4)) { model.StartDate = (lRates.Count == 0) ? scenario.StartDate.Value : ((from d in lRates select d.EndDate).Max()).AddDays(1); model.EndDate = scenario.EndDate.Value; } else { model.StartDate = (from d in lRates select d.EndDate).Max(); model.EndDate = model.StartDate; } } if ((!model.ParentId.HasValue || model.ParentId == Guid.Empty) && parentId.HasValue) model.ParentId = parentId; if (model.ExpenditureCategoryId == Guid.Empty) model.ExpenditureCategoryId = expentureCategoryId; return PartialView("_editRate", model); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult EditRate(RateModel model) { if (ContentLocker.IsLock("Rate", model.Id.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); if(ModelState.IsValid) { var manager = new RateManager(DbContext); manager.Save(model); DbContext.SaveChanges(); manager.Dispose(); } ContentLocker.RemoveLock("Rate", model.Id.ToString(), User.Identity.Name); return JavaScript("window.location.search += '&tab=rateTable';"); //ProcessRates(new RatesModel() { //ExpenditureCategoryId = model.ExpenditureCategoryId, //ScenarioId = model.ParentId.Value, //Mode = RatesModel.FormMode.ListRates }); } [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult DeleteRate(Guid? id) { RateModel model = null; if (id.HasValue && id != Guid.Empty) { var manager = new RateManager(DbContext); model = (RateModel)manager.Load(id); } else model = new RateModel(); return PartialView("_deleteRate", model); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult DeleteRate(RateModel model) { if (ContentLocker.IsLock("Rate", model.Id.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); if (ModelState.IsValid) { var dbObj = DbContext.Rates.FirstOrDefault(x => x.Id == model.Id); DbContext.Rates.Remove(dbObj); DbContext.SaveChanges(); } ContentLocker.RemoveLock("Rate", model.Id.ToString(), User.Identity.Name); return ProcessRates(new RatesModel() { ExpenditureCategoryId = model.ExpenditureCategoryId, ScenarioId = model.ParentId.Value, Mode = RatesModel.FormMode.ListRates }); } public ActionResult GetMonthEndDates(DateTime? StartDate, DateTime? EndDate) { var s = StartDate.Value; var e = EndDate.Value; var dates = (from c in DbContext.FiscalCalendars where c.Type == 1 && c.StartDate >= s && c.EndDate <= e orderby c.StartDate select c.EndDate); var list = new List(); foreach (var d in dates) list.Add(d.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds); return Json(list, JsonRequestBehavior.AllowGet); } [HttpGet] public JsonResult GetTeamCapacityScenarioId(Guid teamId) { using (var context = new EnVisageEntities()) { var data = (from sd in context.Teams where sd.Id == teamId select sd.PlannedCapacityScenarioId).FirstOrDefault(); if (data == null) { var teamManager = new TeamManager(DbContext); var team = teamManager.Load(teamId, false); var scen = new Scenario(); scen.Name = team.Name.Trim() + " Planned Capacity"; scen.Type = (int)ScenarioType.TeamPlannedCapacity; scen.Id = Guid.NewGuid(); team.PlannedCapacityScenarioId = scen.Id; DbContext.Scenarios.Add(scen); DbContext.SaveChanges(); data = scen.Id; } return Json((data == null) ? string.Empty : data.ToString(), JsonRequestBehavior.AllowGet); } } // GET: /Scenario/Delete/5 [HttpGet] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult Delete(Guid? id, string backUrl = null) { if (id == null || id == Guid.Empty) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); var model = new ScenarioModel(); try { var manager = new ScenarioManager(DbContext); model = (ScenarioModel)manager.Load(id); if (model == null) return HttpNotFound(); } catch (BLLException blEx) { if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } } catch (Exception exception) { LogException(exception); SetErrorScript(); } return View(model); } // POST: /Scenario/Delete/5 [HttpPost] [ValidateAntiForgeryToken] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult Delete(ScenarioModel model) { if (ContentLocker.IsLock("Scenario", model.Id.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); var manager = new ScenarioManager(DbContext); var dbObj = manager.Load(model.Id, false); if (dbObj == null) return HttpNotFound(); (DbContext as IObjectContextAdapter).ObjectContext.ExecuteStoreCommand(string.Format("exec sp_DeleteScenario '{0}'", dbObj.Id)); DbContext.SaveChanges(); ContentLocker.RemoveLock("Scenario", dbObj.Id.ToString(), User.Identity.Name); if (Request["backUrl"] != null) { return Redirect(Request["backUrl"]); } else { return RedirectToAction("Index", "Project"); } } [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult AdjustMargin(Guid? id) { var manager = new ScenarioManager(DbContext); var scenario = (ScenarioModel)manager.Load(id, false) ?? new ScenarioModel(); var project = DbContext.Projects.FirstOrDefault(x => x.Id == scenario.ParentId); var model = new UpdateScenarioModel() { Id = scenario.Id, EndDate = scenario.EndDate, Expenditures = scenario.Expenditures, GrossMargin = scenario.GrossMargin, LMMargin = scenario.LMMargin, TDDirectCosts = scenario.TDDirectCosts, ProjectedRevenue = scenario.ProjectedRevenue, StartDate = scenario.StartDate, UseLMMargin = scenario.UseLMMargin, AllowAdjustment = scenario.AllowAdjustment, PriorWeekCutOff = scenario.PriorWeekCutOff ?? scenario.StartDate, BUDirectCosts = scenario.BUDirectCosts }; if (project != null) model.IsRevenueGenerating = project.IsRevenueGenerating; else model.IsRevenueGenerating = false; model.Expenditures = manager.GetExpenditureCategories(model.Id); return PartialView("_adjustMargin", model); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult AdjustMargin(UpdateScenarioModel model, Guid[] expCatId, string[] expCatName, string[] expCatGroup, bool[] expCatChecked) { if (ContentLocker.IsLock("Scenario", model.Id.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); model.TrimStringProperties(); if (expCatId != null && expCatName != null && expCatGroup != null && expCatChecked != null && expCatId.Length == expCatName.Length && expCatId.Length == expCatGroup.Length && expCatId.Length == expCatChecked.Length) { model.Expenditures = new ScenarioModel.ExpenditureItem[expCatId.Length]; for (var i = 0; i < expCatId.Length; i++) { model.Expenditures[i] = new ScenarioModel.ExpenditureItem { Id = expCatId[i], Group = expCatGroup[i], Name = expCatName[i], Checked = expCatChecked[i] }; } } try { // get scenario by id var manager = new ScenarioManager(DbContext); var scenario = (ScenarioModel)manager.Load(model.Id); var project = DbContext.Projects.FirstOrDefault(x => x.Id == scenario.ParentId); if (project != null) model.IsRevenueGenerating = project.IsRevenueGenerating; else model.IsRevenueGenerating = false; if(ModelState.IsValid) { // update scenario values scenario.StartDate = model.StartDate; scenario.EndDate = model.EndDate; scenario.GrossMargin = model.UseLMMargin ? null : model.GrossMargin;//!model.UseLMMargin ? model.GrossMargin / 100 : null; scenario.LMMargin = model.UseLMMargin ? model.LMMargin : null; scenario.TDDirectCosts = model.TDDirectCosts; scenario.ProjectedRevenue = model.ProjectedRevenue; scenario.PriorWeekCutOff = model.PriorWeekCutOff; scenario.AllowAdjustment = model.AllowAdjustment; scenario.UseLMMargin = model.UseLMMargin; scenario.Expenditures = model.Expenditures; scenario.FreezeResource = model.AllowAdjustment; manager.Save(scenario); ContentLocker.RemoveLock("Scenario", model.Id.ToString(), User.Identity.Name); return Json(new { Status = "Ok" }); } } catch (BLLException blEx) { if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } } catch (Exception exception) { LogException(exception); SetErrorScript(); ModelState.AddModelError("errors", "Error on adjust scenario."); } ContentLocker.RemoveLock("Scenario", model.Id.ToString(), User.Identity.Name); return PartialView("_adjustMargin", model); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult CreateTemplate(ScenarioTemplateCreationModel model, Guid[] expCatId, string[] expCatName, string[] expCatGroup, bool[] templateExpCatChecked) { if (ContentLocker.IsLock("Scenario", model.Id.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); model.TrimStringProperties(); if (expCatId != null && expCatName != null && expCatGroup != null && templateExpCatChecked != null && expCatId.Length == expCatName.Length && expCatId.Length == expCatGroup.Length && expCatId.Length == templateExpCatChecked.Length) { model.Expenditures = new ScenarioModel.ExpenditureItem[expCatId.Length]; for (var i = 0; i < expCatId.Length; i++) { model.Expenditures[i] = new ScenarioModel.ExpenditureItem { Id = expCatId[i], Group = expCatGroup[i], Name = expCatName[i], Checked = templateExpCatChecked[i] }; } } var expCatIds = (from e in model.Expenditures where e.Checked == true select e.Id).ToArray(); try { // get scenario by id var manager = new ScenarioManager(DbContext); var scenario = manager.Load(model.Id); if (ModelState.IsValid) { var newTemplate = DbContext.Scenarios.Create(); newTemplate.Id = Guid.NewGuid(); newTemplate.Name = model.TemplateName; newTemplate.ParentId = null; newTemplate.TemplateId = null; newTemplate.Type = (int)ScenarioType.Template; newTemplate.ProjectedRevenue = 0; newTemplate.ExpectedGrossMargin = 0; newTemplate.CalculatedGrossMargin = 0; newTemplate.CGSplit = scenario.CGSplit; newTemplate.EFXSplit = scenario.EFXSplit; newTemplate.StartDate = null; newTemplate.EndDate = null; newTemplate.Duration = scenario.Duration; newTemplate.TDDirectCosts = 0; newTemplate.BUDirectCosts = 0; newTemplate.Shots = scenario.Shots; newTemplate.TDRevenueShot = 0; newTemplate.BURevenueShot = 0; newTemplate.FreezeRevenue = false; newTemplate.Color = null; newTemplate.Status = (int)ScenarioStatus.Active; newTemplate.UseLMMargin = scenario.UseLMMargin; newTemplate.ExpectedGrossMargin_LM = scenario.ExpectedGrossMargin_LM; newTemplate.CalculatedGrossMargin_LM = scenario.CalculatedGrossMargin_LM; newTemplate.TDDirectCosts_LM = 0; newTemplate.BUDirectCosts_LM = 0; newTemplate.BURevenueShot_LM = 0; newTemplate.ShotStartDate = null; newTemplate.GrowthScenario = scenario.GrowthScenario; newTemplate.Actuals_BUDirectCosts = 0; newTemplate.Actuals_BUDirectCosts_LM = 0; newTemplate.SystemAttributeObjectID = scenario.SystemAttributeObjectID; DbContext.Entry(newTemplate).State = EntityState.Added; DbContext.SaveChanges(); var sds = DbContext.ScenarioDetail.Where(s => s.ParentID == scenario.Id && expCatIds.Contains(s.ExpenditureCategoryId.Value)).ToList(); foreach (var scenarioDetails in sds) { var copiedScenarioDetails = DbContext.ScenarioDetail.Create(); copiedScenarioDetails.Cost = scenarioDetails.Cost; copiedScenarioDetails.Id = Guid.NewGuid(); copiedScenarioDetails.ParentID = newTemplate.Id; copiedScenarioDetails.ExpenditureCategoryId = scenarioDetails.ExpenditureCategoryId; copiedScenarioDetails.WeekEndingDate = null; copiedScenarioDetails.Quantity = scenarioDetails.Quantity; copiedScenarioDetails.WeekOrdinal = scenarioDetails.WeekOrdinal; DbContext.Entry(copiedScenarioDetails).State = EntityState.Added; } DbContext.SaveChanges(); ContentLocker.RemoveLock("Scenario", model.Id.ToString(), User.Identity.Name); return Json(new { Status = "Ok" }); } } catch (BLLException blEx) { if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } } catch (Exception exception) { LogException(exception); SetErrorScript(); ModelState.AddModelError("errors", "Error on adjust scenario."); } ContentLocker.RemoveLock("Scenario", model.Id.ToString(), User.Identity.Name); return View(model); } [HttpPost] public JsonResult GetScenarioResources(Guid? scenarioId) { if (scenarioId.HasValue && scenarioId != Guid.Empty) { try { var expCats = DbContext.VW_ExpCategoriesInScenario.Where(x => x.ScenarioID == scenarioId) .Select(x => x.Id).ToList(); var teamsIds = DbContext.Scenarios.FirstOrDefault(x => x.Id == scenarioId) .Project.Company.Teams.Select(t => t.Id).ToList(); var resources = new List(); foreach(var id in expCats) { resources.AddRange(DbContext.PeopleResources .Where(x => x.ExpenditureCategory != null && x.ExpenditureCategory.Id == id) .Select(x => new { Id = x.Id, Name = x.FirstName + " " + x.LastName, Team = x.Team != null ? new { Id = x.Team.Id, Name = x.Team.Name } : null, ExpenditureCategories = x.ExpenditureCategory.Id })); } return Json(new { Status = "Ok", Data = resources }); } catch(Exception ex) { LogException(ex); return Json(new { Status = "Error", Msg = ex.Message }); } } else return Json(new { Status = "Error", Msg = "Param 'scenarioId' can't be null or empty." }); } [HttpPost] public JsonResult GetTeamScenarioResources(Guid? scenarioId) { if (scenarioId.HasValue && scenarioId != Guid.Empty) { try { var expCats = DbContext.VW_ExpCategoriesInScenario.Where(x => x.ScenarioID == scenarioId) .Select(x => x.Id).ToList(); var team = DbContext.Teams.FirstOrDefault(x => x.PlannedCapacityScenarioId == scenarioId); var teamId = team.Id; var teamName = team.Name; var resources = new List(); foreach (var id in expCats) { resources.AddRange(DbContext.PeopleResources .Where(x => x.ExpenditureCategory != null && x.ExpenditureCategory.Id == id).AsEnumerable() .Select(x => new { Id = x.Id, Name = x.FirstName + " " + x.LastName, Team = new { Id = teamId, Name = teamName }, ExpenditureCategories = x.ExpenditureCategory.Id })); } return Json(new { Status = "Ok", Data = resources }); } catch (Exception ex) { LogException(ex); return Json(new { Status = "Error", Msg = ex.Message }); } } else return Json(new { Status = "Error", Msg = "Param 'scenarioId' can't be null or empty." }); } [HttpPost] [AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)] public ActionResult DeleteAllLocalRates(Guid? scenarioId, Guid? expenditureCategoryId) { if (!scenarioId.HasValue || scenarioId == Guid.Empty || !expenditureCategoryId.HasValue || expenditureCategoryId == Guid.Empty) return Json(new { Status = "Error", Msg = "Parameter scenarioId or expenditureCategoryId can not be null or empty." }); if (ContentLocker.IsLock("Scenario", scenarioId.ToString(), User.Identity.Name)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); try { var ratesForDelete = DbContext.Rates .Where(x => x.ParentId == scenarioId && x.ExpenditureCategoryId == expenditureCategoryId && x.Type == (short)RateModel.RateType.Derived); DbContext.Rates.RemoveRange(ratesForDelete); DbContext.SaveChanges(); ContentLocker.RemoveLock("Scenario", scenarioId.ToString(), User.Identity.Name); return Json(new { Status = "Ok" }); } catch (Exception exception) { LogException(exception); return Json(new { Status = "Error", Msg = exception.Message }); } } } }