EnVisageOnline/Beta/Source/EnVisage/Controllers/ScenariosController.cs

2223 lines
103 KiB
C#

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<Dictionary<Guid, short>>(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<ScenarioCostSavingModel>()
: Newtonsoft.Json.JsonConvert.DeserializeObject<List<ScenarioCostSavingModel>>
(model.CostSavingItems) ?? new List<ScenarioCostSavingModel>();
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<Dictionary<Guid, short>>(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);
}
/// <summary>
/// Returns JSON UnitOfMeasure list with filters and sort for jQuery DataTables
/// </summary>
[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<ScenarioListItemModel> GetTemplates(int startIndex,
int pageSize,
IEnumerable<SortedColumn> 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<ScenarioModel.ExpenditureItem>());
}
// 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<ExpenditureModel> expCatList = new List<ExpenditureModel>();
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<Guid>();
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<ScenarioDetailsModel.ScenarioCalendarRow>
{
// 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<Guid>();
model.AllResources = new List<ScenarioDetailsModel.ScenarioCalendarRowResource>();
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<DateTime> gridHeaders)
{
model.Headers = new List<ScenarioDetailsModel.Header>((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<int>()
};
}
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<double>();
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<object>();
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<object>();
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 });
}
}
}
}