EnVisageOnline/Beta/Source/EnVisage/Controllers/CapacityManagementControlle...

1204 lines
67 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using EnVisage;
using EnVisage.Code;
using EnVisage.Code.BLL;
using EnVisage.Code.HtmlHelpers;
using EnVisage.Models;
using Microsoft.AspNet.Identity;
using jQuery.DataTables.Mvc;
using EnVisage.App_Start;
using EnVisage.Code.Cache;
namespace EnVisage.Controllers
{
[Authorize]
public class CapacityManagementController : BaseController
{
private class Pairs
{
public Guid Id { get; set; }
public decimal Quantity { get; set; }
}
/// <summary>
/// Direct GET to the page - returns main view
/// </summary>
public ActionResult Index(string menuId, string additionalFilters, PagePreferencesList.PagePreferencesSource src)
{
return PartialView("_capacityManagement",
new CapacityDetailsOptionsModel { MenuId = menuId, AdditionalFilterParams = additionalFilters, Source = src });
}
/// <summary>
/// GET: /Clients/
/// </summary>
/// <returns>Empty view</returns>
[HttpGet]
[AreaSecurityAttribute(area = Areas.Clients, level = AccessLevel.Read)]
public ActionResult Index()
{
var user = new UsersCache().Value.FirstOrDefault(x => x.Id == new Guid(HttpContext.User.Identity.GetUserId()));
if (user != null)
ViewBag.IsUOMHours = !user.PreferredResourceAllocation;
return View();
}
[HttpPost]
public ActionResult GetCompanies()
{
return Json(
DbContext.Companies.AsNoTracking().Select(c=>
new SelectListItem() {
Text = c.Name,
Value=c.Id.ToString()
}).ToList());
}
[HttpPost]
public ActionResult LoadJsonCalendar(CapacityDetailsModel model)
{
if (model == null || ((model.CompanyId == null || model.CompanyId == Guid.Empty)
&& (model.TeamId == null ||model.TeamId == Guid.Empty)
&& (model.ViewId == null || model.ViewId == Guid.Empty)))
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
if (model.CompanyId != null && model.CompanyId != Guid.Empty)
{
var company = DbContext.Companies.AsNoTracking().FirstOrDefault(t => t.Id == model.CompanyId);
if (company == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
if (model.TeamId != null && model.TeamId != Guid.Empty)
{
var team = DbContext.Teams.AsNoTracking().FirstOrDefault(t => t.Id == model.TeamId);
if (team == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
if (model.ViewId != null && model.ViewId != Guid.Empty)
{
var team = DbContext.Views.AsNoTracking().FirstOrDefault(t => t.Id == model.ViewId);
if (team == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
model.StartDate = DateTime.Today;
model.EndDate = DateTime.Today.AddYears(1);
return Json(GetCalendar(model), JsonRequestBehavior.AllowGet);
}
/// <summary>
/// Returns a list of all principal GUIDs (user himself and his roles) to be used in direct requests to Security and ProjectAccess tables
/// </summary>
private Guid[] GetUserPrincipals()
{
var userId = User.Identity.GetUserId();
AspNetUser user = (from c in DbContext.AspNetUsers where c.Id == userId select c).FirstOrDefault();
var roleids = (from c in user.AspNetRoles select c.Id).ToList();
roleids.Add(userId);
var result = new Guid[roleids.Count() + 1];
for (int i = 0; i < roleids.Count(); i++)
result[i] = new Guid(roleids[i]);
result[roleids.Count()] = new Guid(userId);
return result;
}
private CapacityDetailsModel GetCalendar(CapacityDetailsModel model)
{
DateTime periodStartDate;
DateTime periodEndDate;
Guid actualScenarioId = Guid.Empty;
periodStartDate = model.StartDate;
periodEndDate = model.EndDate;
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var calendarList = new List<CapacityDetailsModel.CalendarRow>();
var totalsList = new List<CapacityDetailsModel.CalendarRow>();
var principals = GetUserPrincipals();
var projectAccesses = new ProjectAccessCache().Value.Where(x => principals.Contains(x.PrincipalId)).Select(x => x.ProjectId);
List<Project> projects = null;
var teamIds = new List<Guid>();
var teams = new List<Team>();
var groupByTeamMode = model.GroupByTeam ?? false;
#region Collect common data
if (model.CompanyId != null && !model.CompanyId.Equals(Guid.Empty))
{
var companyIds = DbContext.Companies.Where(c => c.ParentCompanyId == model.CompanyId).Select(c=>c.Id).ToList();
companyIds.Add(model.CompanyId.Value);
projects = DbContext.Projects.Where(p => p.CompanyId.HasValue && companyIds.Contains(p.CompanyId.Value) && projectAccesses.Contains(p.Id) && !p.HasChildren).AsNoTracking().ToList();
projects.ForEach(p => p.Team2Project.Where(t2p=>!teams.Select(t => t.Id).Contains(t2p.TeamId)).ToList().ForEach(t => teams.Add(t.Team)));
teamIds.AddRange(teams.Select(t=>t.Id));
}
else if(model.TeamId != null && !model.TeamId.Equals(Guid.Empty)){
groupByTeamMode = false;
projects = DbContext.Team2Project.Where(p => p.TeamId == model.TeamId && projectAccesses.Contains(p.ProjectId) && !p.Project.HasChildren).Select(x => x.Project).AsNoTracking().ToList();
projects.ForEach(p => p.Team2Project.Where(t2p => model.TeamId == t2p.TeamId && !teams.Select(t => t.Id).Contains(t2p.TeamId)).ToList().ForEach(t => teams.Add(t.Team)));
teamIds.AddRange(teams.Select(t => t.Id));
}
else if (model.ViewId != null && !model.ViewId.Equals(Guid.Empty))
{
var viewTeamIds = (from tv in DbContext.Team2View
where tv.ViewId == model.ViewId
select tv.TeamId).ToList();
teamIds.AddRange(viewTeamIds);
projects = DbContext.Team2Project.Where(p => teamIds.Contains(p.TeamId) && projectAccesses.Contains(p.ProjectId) && !p.Project.HasChildren).
Select(x => x.Project).AsNoTracking().Distinct().ToList();
projects.ForEach(p => p.Team2Project.Where(t2p => teamIds.Contains(t2p.TeamId) && !teams.Select(t => t.Id).Contains(t2p.TeamId)).ToList().ForEach(t => teams.Add(t.Team)));
}
if (!model.GroupByTeam.HasValue || !model.GroupByTeam.Value || teams.Count() == 0)
{
teams = new List<Team>() { new Team(){Id = Guid.Empty} };
}
var projectIds = new List<Guid>();
projects.ForEach(p =>
projectIds.Add(p.Id));
var scenarioIds = new List<Guid>();
projects.ForEach(p=>
p.Scenarios.Where(s => s.Status.HasValue && s.Status.Value == (int)ScenarioStatus.Active
&& s.Type == (int)ScenarioType.Portfolio)
.ToList().ForEach(s => scenarioIds.Add(s.Id)));
var resourceAllocation = DbContext.PeopleResourceAllocations.Where(r => scenarioIds.Contains(r.ScenarioId)).ToList();
model.AllResources = new List<CapacityDetailsModel.ScenarioCalendarRowResource>();
var resourcesByTeams = DbContext.Teams.AsNoTracking().Where(x => teamIds.Contains(x.Id)).
Select(x => x.PeopleResources);
foreach (var teamResource in resourcesByTeams)
{
model.AllResources.AddRange(teamResource.Where(tr=>!model.AllResources.Select(ar=>ar.Id).Contains(tr.Id)).
Select(x => new CapacityDetailsModel.ScenarioCalendarRowResource()
{
Id = x.Id,
Name = string.Format("{0} {1}", x.FirstName, x.LastName),
ExpedentureCategoryId = x.ExpenditureCategoryId,
TeamId = x.TeamId.Value,
AssignedToTeam = teamIds.Contains(x.TeamId.Value),
ProjectIds = projects.SelectMany(p => p.Team2Project).Where(p => p.TeamId == x.TeamId.Value).Select(p=>p.ProjectId).ToArray(),
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 scenarioDetails = DbContext.VW_ScenarioAndProxyDetails.AsNoTracking()
.Where(t => t.ParentID.HasValue && scenarioIds.Contains(t.ParentID.Value) &&
t.WeekEndingDate >= periodStartDate &&
t.WeekEndingDate <= periodEndDate).OrderBy(t => t.ExpenditureCategoryName).ThenBy(t => t.WeekEndingDate);
Dictionary<Guid, List<Team2Scenario>> teams2scenarios =
DbContext.Team2Scenario.AsNoTracking().Where(t2s => scenarioIds.Contains(t2s.ScenarioId)).GroupBy(t2s => t2s.ScenarioId).ToDictionary(key => key.Key, grouping => grouping.ToList());
var scenarioDetailsInternal = scenarioDetails.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 itemsCount = 0;
CapacityDetailsModel.CalendarRow vacationRow = null;
CapacityDetailsModel.CalendarRow trainingRow = null;
CapacityDetailsModel.CalendarRow capacityRow = null;
CapacityDetailsModel.CalendarRow grandTotalRow = null;
var headerDates = (from c in DbContext.FiscalCalendars where c.Type == 0 && c.StartDate >= model.StartDate && c.EndDate <= model.EndDate orderby c.StartDate select c.EndDate);
BuildHeaders(model, headerDates.ToList());
itemsCount = model.Headers.Count;
#region Add Total (Active Scenarios), Vacation, Training, Loan-outs, Capacity
grandTotalRow = new CapacityDetailsModel.CalendarRow()
{
Name = "Total (Active Scenarios)",
QuantityValues = new decimal[model.Headers.Count],
IsParentCollapsed = false,
IsTotals = true,
RowType = CapacityDetailsModel.RowType.Total
};
vacationRow = new CapacityDetailsModel.CalendarRow
{
Name = "Vacation",
QuantityValues = new decimal[model.Headers.Count],
IsParentCollapsed = false,
IsTotals = true,
RowType = CapacityDetailsModel.RowType.Vacation
};
totalsList.Add(vacationRow);
trainingRow= new CapacityDetailsModel.CalendarRow()
{
Name = "Training",
QuantityValues = new decimal[model.Headers.Count],
IsParentCollapsed = false,
IsTotals = true,
RowType = CapacityDetailsModel.RowType.Training
};
totalsList.Add(trainingRow);
//ENV-623 Hide loan-outs, as there is no way to input them or use the feature in the system, yet.
//totalsList.Add(new CapacityDetailsModel.CalendarRow()
//{
// Name = "Loan-outs",
// QuantityValues = new decimal[model.Headers.Count],
// IsParentCollapsed = false,
// IsTotals = true,
// RowType = CapacityDetailsModel.RowType.LoanOut
//});
totalsList.Add(grandTotalRow);
capacityRow = new CapacityDetailsModel.CalendarRow()
{
Name = "Capacity",
QuantityValues = new decimal[model.Headers.Count],
IsParentCollapsed = false,
IsTotals = true,
RowType = CapacityDetailsModel.RowType.Capacity
};
totalsList.Add(capacityRow);
#endregion
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;
}
var allExpCats = DbContext.ExpenditureCategory.AsNoTracking().ToList();
var allUoms = DbContext.UOMs.AsNoTracking().ToList();
model.AllResources.ForEach(res =>
{
res.VacationQuantityValues = new decimal[itemsCount];
res.TrainingQuantityValues = new decimal[itemsCount];
});
#endregion
foreach (var team in teams)
{
var groupByTeam = !Guid.Empty.Equals(team.Id);
if (groupByTeam && groupByTeamMode)
{
//Add Team row
calendarList.Add(new CapacityDetailsModel.CalendarRow()
{
Name = team.Name,
RowType = CapacityDetailsModel.RowType.Team,
});
}
foreach (var project in projects.Where(p => !groupByTeam || p.Team2Project.Select(t2p => t2p.TeamId).Contains(team.Id)).OrderBy(p => p.Name).ThenBy(p => p.Id))
{
var projectActiveScenarios = project.Scenarios.Where(s => s.Status.HasValue && s.Status.Value == (int)ScenarioStatus.Active
&& s.Type == (int)ScenarioType.Portfolio).OrderBy(p => p.Name).ThenBy(p => p.Id);
if (!projectActiveScenarios.Any())
continue;
#region Add Project row
calendarList.Add(new CapacityDetailsModel.CalendarRow() {
ProjectId = project.Id,
Name = (project.ParentProject != null ? project.ParentProject.Name + ": " : "") + project.Name,
Color = !string.IsNullOrEmpty(project.Color) ? project.Color.Contains('#') ? project.Color : "#" + project.Color :
(project.ParentProject != null ? project.ParentProject.Color.Contains('#') ? project.ParentProject.Color : "#" + project.ParentProject.Color : null ),
DetailIds = new Guid?[itemsCount],
QuantityValues = new decimal[itemsCount],
SpreadVal = new CapacityDetailsModel.Spread[itemsCount],
IsParentCollapsed = false,
ExpCatId = null,
ScenarioId = null,
RowType = CapacityDetailsModel.RowType.Project,
ReadOnly = new bool[itemsCount],
TeamId = team.Id
});
#endregion
foreach (var scenario in projectActiveScenarios)
{
var projectRow = calendarList.FirstOrDefault(x => x.ProjectId == project.Id && x.TeamId == team.Id && x.ExpCatId == null);
#region Add Scenario to Project row
if (projectRow != null && projectRow.ScenarioId == null)
{
projectRow.ScenarioId = scenario.Id;
projectRow.Name1 = scenario.Name;
var dates1 = scenarioDetailsInternal.Where(sd => sd.Key.ParentID == scenario.Id).SelectMany(x => x.Value).ToList();
var dates = dates1.Select(x => x.WeekEndingDate.Value).ToList();
if (dates.Count > 0)
projectRow.StartDate = (long)dates.Min().Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
if (dates.Count > 0)
projectRow.EndDate = (long)dates.Max().Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
}
#endregion
List<Guid?> project2ExpCats = null;
if (groupByTeam)
{
project2ExpCats = model.AllResources.Where(r => team.Id.Equals(r.TeamId)).Select(r => r.ExpedentureCategoryId).ToList();
}
else
{
project2ExpCats = model.AllResources.Where(r => teamIds.Contains(r.TeamId)).Select(r => r.ExpedentureCategoryId).ToList();
}
//Filter all ExpCats by available resorces
var expCats = scenarioDetailsInternal.Where(sd => sd.Key.ParentID == scenario.Id &&
project2ExpCats.Contains(sd.Key.ExpenditureCategoryId.Value));
decimal teamAssignmentMultiplier = 0;
if (groupByTeam)
{
teamAssignmentMultiplier = GetProjectNeedMultiplier(scenario.Id, new List<Guid>(){ team.Id}, teams2scenarios);
}
else
{
teamAssignmentMultiplier = GetProjectNeedMultiplier(scenario.Id, teamIds, teams2scenarios);
}
foreach (var expCat in expCats)
{
#region Add exp cat row for the top part of the calendar
calendarList.Add(new CapacityDetailsModel.CalendarRow()
{
ProjectId = project.Id,
ScenarioId = scenario.Id,
TeamId = team.Id,
ExpCatId = expCat.Key.ExpenditureCategoryId,
Name = expCat.Key.ExpenditureCategoryName,
DetailIds = new Guid?[itemsCount],
QuantityValues = new decimal[itemsCount],
SpreadVal = new CapacityDetailsModel.Spread[itemsCount],
CollapsedClass = "fa-plus-square-2",
RestQuantity = new decimal[itemsCount],
ReadOnly = new bool[itemsCount],
EmptyScenario = false,
RowType = CapacityDetailsModel.RowType.ProjectExpenditureCategory,
Resources = model.AllResources.Where(x => resourceAllocation.Where(ec => ec.ExpenditureCategoryId == expCat.Key.ExpenditureCategoryId
&& ec.ScenarioId == scenario.Id && (!groupByTeam || (groupByTeam && team.Id == x.TeamId)))
.Select(r => r.PeopleResourceId).Contains(x.Id))
.Select(x => new CapacityDetailsModel.ScenarioCalendarRowResource()
{
Id = x.Id,
Name = x.Name,
QuantityValues = new decimal[itemsCount],
CapacityQuantityValues = new decimal[itemsCount],
VacationQuantityValues = new decimal[itemsCount],
TrainingQuantityValues = new decimal[itemsCount],
ReadOnly = !teamIds.Contains(x.TeamId),
IsActiveEmployee = x.IsActiveEmployee,
TeamId = x.TeamId
}).ToList(),
});
#endregion
var expCatRow = calendarList.Last();
#region Add exp cat row for the bottom part of the calendar
var totalsListExpCat = totalsList.FirstOrDefault(t=>t.ExpCatId == expCatRow.ExpCatId);
if (totalsListExpCat == null)
{
totalsListExpCat = new CapacityDetailsModel.CalendarRow()
{
ExpCatId = expCat.Key.ExpenditureCategoryId,
Name = expCat.Key.ExpenditureCategoryName,
QuantityValues = new decimal[itemsCount],
SpreadVal = new CapacityDetailsModel.Spread[itemsCount],
CollapsedClass = "fa-plus-square",
IsParentCollapsed = false,
EmptyScenario = false,
QuantityTotalResValue = new decimal[itemsCount],
QuantityExpCatTotalValue = new decimal[itemsCount],
RowType = CapacityDetailsModel.RowType.BottomCategory,
Resources = new List<CapacityDetailsModel.ScenarioCalendarRowResource>(model.AllResources.
Where(x => x.ExpedentureCategoryId == expCat.Key.ExpenditureCategoryId && teamIds.Contains(x.TeamId)).Select(x =>
new CapacityDetailsModel.ScenarioCalendarRowResource()
{
Id = x.Id,
ExpedentureCategoryId = x.ExpedentureCategoryId,
Name = x.Name,
QuantityValues = new decimal[itemsCount],
SpreadVal = new CapacityDetailsModel.Spread[itemsCount],
QuantityTotalResValue = new decimal[itemsCount],
VacationQuantityValues = new decimal[itemsCount],
TrainingQuantityValues = new decimal[itemsCount],
GrandTotalCost = 0M,
GrandTotalQuantity = 0M,
IsActiveEmployee = x.IsActiveEmployee,
TeamId = x.TeamId
}))
};
totalsList.Add(totalsListExpCat);
}
#endregion
projectRow.EmptyScenario = false;
var uomMultiplier = Utils.GetUOMMultiplier(allExpCats, allUoms, expCat.Key.ExpenditureCategoryId ?? Guid.Empty, model.IsUOMHours);
var expCatUOM = allUoms.FirstOrDefault(t => t.Id == expCat.Key.UOMId);
var uomValue = expCatUOM == null ? 0 : expCatUOM.UOMValue*uomMultiplier;
expCatRow.Resources.ForEach(r => r.Title = (expCatRow.Resources.Exists(r1 => r1.ReadOnly) ?
"There are resources from other team assigned to the category so you cannot use Take all" : "Take all"));
var monthQuantity = 0.0M;
var monthVacation = 0.0M;
var monthTraining = 0.0M;
var monthResVal = 0.0M;
var monthResTotalVal = 0.0M;
var weeksCount = 0;
var resourceTotals = model.AllResources.Select(x => x.Id).ToDictionary(key => key, pairs => 0.0M);
var resourceTotalsExpCatTotals = model.AllResources.Select(x => new Pairs() { Id = x.Id, Quantity = 0.0M }).ToList();
var isMonthReadOnly = true;
// iterate through the weeks/months collection (1 month item following 4/5 week items)
for (int colIndex = 0; colIndex < itemsCount; colIndex++)
{
var isScenarioDate = (model.Headers[colIndex].Milliseconds >= projectRow.StartDate &&
model.Headers[colIndex].Milliseconds <= projectRow.EndDate);
expCatRow.ReadOnly[colIndex] = !isScenarioDate;
projectRow.ReadOnly[colIndex] = !isScenarioDate;
isMonthReadOnly &= !isScenarioDate;
// if item is a new week
if (!model.Headers[colIndex].IsMonth)
{
if (isScenarioDate)
{
var val = expCat.Value.FirstOrDefault(x => x.WeekEndingDate.Value.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds == model.Headers[colIndex].Milliseconds); //[colIndex1];
if (val != null)
{
expCatRow.DetailIds[colIndex] = val.Id; // column.Id;
expCatRow.QuantityValues[colIndex] = (val.Quantity ?? 0) * uomMultiplier * teamAssignmentMultiplier; // (column.Quantity ?? 0) * uomMultiplier;
monthQuantity += expCatRow.QuantityValues[colIndex];
}
}
else
{
expCatRow.QuantityValues[colIndex] = 0;
expCatRow.DetailIds[colIndex] = null;
}
weeksCount++;
//Project/Scenario row update
projectRow.QuantityValues[colIndex] += expCatRow.QuantityValues[colIndex];
grandTotalRow.QuantityValues[colIndex] += expCatRow.QuantityValues[colIndex];
//Get resources quantity
var date = epoch.AddSeconds(model.Headers[colIndex].Milliseconds / 1000);
//Get allocation for the date
var currAllocation = resourceAllocation.Where(r => r.WeekEndingDate == date
&& r.ExpenditureCategoryId == expCatRow.ExpCatId && r.ScenarioId == expCatRow.ScenarioId).ToList();
expCatRow.Resources.ForEach(x =>
{
var peopleResourceAllocation = currAllocation.FirstOrDefault(ar => ar.PeopleResourceId == x.Id);
if (peopleResourceAllocation != null)
x.QuantityValues[colIndex] = (peopleResourceAllocation.Quantity ?? 0) * uomMultiplier;
else
x.QuantityValues[colIndex] = 0;
if (expCatUOM != null)
{
var vacationsSum = allResourceVacations.Where(t => t.PeopleResourceId == x.Id &&
t.WeekEndingDate <= date && t.WeekEndingDate >= date.AddDays(-6))
.Sum(s => s.HoursOff);
vacationRow.QuantityValues[colIndex] += vacationsSum * uomMultiplier;
monthVacation += vacationsSum * uomMultiplier;
grandTotalRow.QuantityValues[colIndex] += vacationsSum * uomMultiplier;
var trainingsSum = allResourceTrainings.Where(t => t.PeopleResourceId == x.Id &&
t.WeekEndingDate <= date && t.WeekEndingDate >= date.AddDays(-6))
.Sum(s => s.HoursOff);
trainingRow.QuantityValues[colIndex] += trainingsSum * uomMultiplier;
monthTraining += trainingsSum * uomMultiplier;
grandTotalRow.QuantityValues[colIndex] += trainingsSum * uomMultiplier;
x.CapacityQuantityValues[colIndex] = (expCatUOM.UOMValue - vacationsSum - trainingsSum) * uomMultiplier;
}
if (resourceTotals.ContainsKey(x.Id))
resourceTotals[x.Id] += x.QuantityValues[colIndex];
});
//Calculate not allocated quantity
expCatRow.RestQuantity[colIndex] = expCatRow.QuantityValues[colIndex] -
expCatRow.Resources.Select(x => x.QuantityValues[colIndex]).Sum() * uomMultiplier;
//Add resources to the capacity EC
foreach (var resCloneFrom in expCatRow.Resources)
{
var resCloneTo = totalsListExpCat.Resources.FirstOrDefault(r => resCloneFrom.Id == r.Id);
if (resCloneTo != null)
{
resCloneTo.QuantityValues[colIndex] += resCloneFrom.QuantityValues[colIndex];
}
}
totalsListExpCat.QuantityExpCatTotalValue[colIndex] += expCatRow.QuantityValues[colIndex];
#region Set validation class
var resTotal = expCatRow.Resources.Select(r => r.QuantityValues[colIndex]).Sum();
var compareRes = compareValues(resTotal, expCatRow.QuantityValues[colIndex]);
expCatRow.SpreadVal[colIndex] = compareRes == 0 ? CapacityDetailsModel.Spread.Equal :
compareRes > 0 ? CapacityDetailsModel.Spread.Over :
compareRes < 0 ? CapacityDetailsModel.Spread.Less : CapacityDetailsModel.Spread.Notspecified;
if (projectRow.SpreadVal[colIndex] != CapacityDetailsModel.Spread.Over)
{
if (projectRow.SpreadVal[colIndex] != CapacityDetailsModel.Spread.Less)
{
if (expCatRow.SpreadVal[colIndex] != CapacityDetailsModel.Spread.Notspecified)
{
projectRow.SpreadVal[colIndex] = expCatRow.SpreadVal[colIndex];
}
}
else
{
if (expCatRow.SpreadVal[colIndex] == CapacityDetailsModel.Spread.Over)
{
projectRow.SpreadVal[colIndex] = expCatRow.SpreadVal[colIndex];
}
}
}
#endregion
//EC capacity
totalsListExpCat.QuantityResValue = uomValue;
totalsListExpCat.QuantityValues[colIndex] = totalsListExpCat.Resources.Select(x => x.QuantityValues[colIndex]).Sum();
expCatRow.Resources.ForEach(x =>
resourceTotalsExpCatTotals.FirstOrDefault(r => r.Id == x.Id).Quantity += x.QuantityValues[colIndex]);
totalsListExpCat.QuantityTotalResValue[colIndex] = totalsListExpCat.Resources.Where(r => r.IsActiveEmployee).Count() * uomValue;
totalsListExpCat.Resources.ForEach(r =>
r.QuantityTotalResValue[colIndex] = (r.IsActiveEmployee ? uomValue : 0));
monthResTotalVal += totalsListExpCat.QuantityTotalResValue[colIndex];
monthResVal += uomValue;
#region Set validation class
compareRes = compareValues(totalsListExpCat.QuantityValues[colIndex], totalsListExpCat.QuantityTotalResValue[colIndex]);
totalsListExpCat.SpreadVal[colIndex] = compareRes == 0 ? CapacityDetailsModel.Spread.Equal :
compareRes > 0 ? CapacityDetailsModel.Spread.Over :
compareRes < 0 ? CapacityDetailsModel.Spread.Less : CapacityDetailsModel.Spread.Notspecified;
totalsListExpCat.Resources.ForEach(r => r.SpreadVal[colIndex] = r.QuantityValues[colIndex] == r.QuantityTotalResValue[colIndex] ? CapacityDetailsModel.Spread.Equal :
r.QuantityValues[colIndex] > r.QuantityTotalResValue[colIndex] ? CapacityDetailsModel.Spread.Over :
r.QuantityValues[colIndex] < r.QuantityTotalResValue[colIndex] ? CapacityDetailsModel.Spread.Less : CapacityDetailsModel.Spread.Notspecified);
#endregion
}
else//if (model.Headers[colIndex].IsMonth) if item is a month then let's summarize data of it's weeks
{
expCatRow.DetailIds[colIndex] = Guid.Empty;
expCatRow.QuantityValues[colIndex] = monthQuantity;
expCatRow.ReadOnly[colIndex] = isMonthReadOnly;
projectRow.ReadOnly[colIndex] = isMonthReadOnly;
isMonthReadOnly = true;
expCatRow.Resources.ForEach(x =>
{
x.QuantityValues[colIndex] = resourceTotals.ContainsKey(x.Id)
? resourceTotals[x.Id]
: 0;
});
vacationRow.QuantityValues[colIndex] += monthVacation;
trainingRow.QuantityValues[colIndex] += monthTraining;
grandTotalRow.QuantityValues[colIndex] += monthVacation + monthTraining;
totalsListExpCat.QuantityExpCatTotalValue[colIndex] += expCatRow.QuantityValues[colIndex];
//Project/Scenario row update
projectRow.QuantityValues[colIndex] += expCatRow.QuantityValues[colIndex];
grandTotalRow.QuantityValues[colIndex] += expCatRow.QuantityValues[colIndex];
#region Set validation class
var resTotal = expCatRow.Resources.Select(r => r.QuantityValues[colIndex]).Sum();
var compareRes = compareValues(resTotal, expCatRow.QuantityValues[colIndex]);
expCatRow.SpreadVal[colIndex] = compareRes == 0 ? CapacityDetailsModel.Spread.Equal :
compareRes > 0 ? CapacityDetailsModel.Spread.Over :
compareRes < 0 ? CapacityDetailsModel.Spread.Less : CapacityDetailsModel.Spread.Notspecified;
if (projectRow.SpreadVal[colIndex] != CapacityDetailsModel.Spread.Over)
{
if (projectRow.SpreadVal[colIndex] != CapacityDetailsModel.Spread.Less)
{
if (expCatRow.SpreadVal[colIndex] != CapacityDetailsModel.Spread.Notspecified)
{
projectRow.SpreadVal[colIndex] = expCatRow.SpreadVal[colIndex];
}
}
else
{
if (expCatRow.SpreadVal[colIndex] == CapacityDetailsModel.Spread.Over)
{
projectRow.SpreadVal[colIndex] = expCatRow.SpreadVal[colIndex];
}
}
}
//expCatRow.Resources.ForEach(r => r.SpreadVal[colIndex] = expCatRow.SpreadVal[colIndex]);
#endregion
totalsListExpCat.QuantityTotalResValue[colIndex] = monthResTotalVal; // totalsListExpCat.Resources.Count* UoMVal;
totalsListExpCat.Resources.ForEach(x =>
{
x.QuantityTotalResValue[colIndex] = (x.IsActiveEmployee ? monthResVal : 0);
x.QuantityValues[colIndex] += resourceTotalsExpCatTotals.FirstOrDefault(r => r.Id == x.Id).Quantity;
});
totalsListExpCat.QuantityValues[colIndex] = totalsListExpCat.Resources.Select(x => x.QuantityValues[colIndex]).Sum();
totalsListExpCat.QuantityResValue = uomValue;
#region Set validation class to total exp cat row
compareRes = compareValues(totalsListExpCat.QuantityValues[colIndex], totalsListExpCat.QuantityTotalResValue[colIndex]);
totalsListExpCat.SpreadVal[colIndex] = compareRes == 0 ? CapacityDetailsModel.Spread.Equal :
compareRes > 0 ? CapacityDetailsModel.Spread.Over :
compareRes < 0 ? CapacityDetailsModel.Spread.Less : CapacityDetailsModel.Spread.Notspecified;
compareRes = compareValues(totalsListExpCat.QuantityValues[colIndex], totalsListExpCat.QuantityTotalResValue[colIndex]);
totalsListExpCat.Resources.ForEach(r => r.SpreadVal[colIndex] = compareValues(r.QuantityValues[colIndex], r.QuantityTotalResValue[colIndex]) == 0 ? CapacityDetailsModel.Spread.Equal :
compareValues(r.QuantityValues[colIndex], r.QuantityTotalResValue[colIndex]) > 0 ? CapacityDetailsModel.Spread.Over :
compareValues(r.QuantityValues[colIndex], r.QuantityTotalResValue[colIndex]) > 0 ? CapacityDetailsModel.Spread.Less : CapacityDetailsModel.Spread.Notspecified);
#endregion
monthQuantity = 0.0M;
monthVacation = 0.0M;
monthTraining = 0.0M;
monthResVal = 0.0M;
monthResTotalVal = 0.0M;
weeksCount = 0;
var keys = resourceTotals.Keys.ToArray();
foreach (var key in keys)
{
resourceTotals[key] = 0.0M;
}
resourceTotalsExpCatTotals.ForEach(x => x.Quantity = 0.0M);
}
}
}
}
}
}
model.Calendar = calendarList;
if (totalsList.Count == 0)
{
var dates = (from c in DbContext.FiscalCalendars where c.Type == 0 && c.StartDate >= model.StartDate && c.EndDate <= model.EndDate orderby c.StartDate select c.EndDate);
BuildHeaders(model, dates.ToList());
#region Add Total (Active Scenarios), Vacation, Training, Loan-outs, Capacity
grandTotalRow = new CapacityDetailsModel.CalendarRow()
{
Name = "Total (Active Scenarios)",
QuantityValues = new decimal[model.Headers.Count],
IsParentCollapsed = false,
IsTotals = true,
RowType = CapacityDetailsModel.RowType.Total
};
vacationRow = new CapacityDetailsModel.CalendarRow
{
Name = "Vacation",
QuantityValues = new decimal[model.Headers.Count],
IsParentCollapsed = false,
IsTotals = true,
RowType = CapacityDetailsModel.RowType.Vacation
};
totalsList.Add(vacationRow);
trainingRow= new CapacityDetailsModel.CalendarRow()
{
Name = "Training",
QuantityValues = new decimal[model.Headers.Count],
IsParentCollapsed = false,
IsTotals = true,
RowType = CapacityDetailsModel.RowType.Training
};
totalsList.Add(trainingRow);
totalsList.Add(new CapacityDetailsModel.CalendarRow()
{
Name = "Loan-outs",
QuantityValues = new decimal[model.Headers.Count],
IsParentCollapsed = false,
IsTotals = true,
RowType = CapacityDetailsModel.RowType.LoanOut
});
totalsList.Add(grandTotalRow);
totalsList.Add(new CapacityDetailsModel.CalendarRow()
{
Name = "Capacity",
QuantityValues = new decimal[model.Headers.Count],
IsParentCollapsed = false,
IsTotals = true,
RowType = CapacityDetailsModel.RowType.Capacity
});
#endregion
}
totalsList.ForEach(ec =>
ec.EmptyScenario = (ec.Resources == null || !ec.Resources.Any()));
#region Add expected EC
var totalExpCats = DbContext.PeopleResources.Where(r => teamIds.Contains(r.TeamId.Value)).Select(r => r.ExpenditureCategory).Distinct().ToList();
var remainingExpCats = totalExpCats.Where(ec => !totalsList.Select(ec1 => ec1.ExpCatId).Contains(ec.Id)).ToList();
var d = remainingExpCats.Select(ec => new CapacityDetailsModel.CalendarRow()
{
ExpCatId = ec.Id,
Name = ec.Expenditure.Name,
QuantityValues = new decimal[model.Headers.Count],
SpreadVal = new CapacityDetailsModel.Spread[model.Headers.Count],
CollapsedClass = "fa-plus-square",
IsParentCollapsed = false,
EmptyScenario = false,
QuantityTotalResValue = new decimal[model.Headers.Count],
QuantityExpCatTotalValue = new decimal[model.Headers.Count],
RowType = CapacityDetailsModel.RowType.BottomCategory,
Resources = new List<CapacityDetailsModel.ScenarioCalendarRowResource>(model.AllResources.
Where(x => x.ExpedentureCategoryId == ec.Id && teamIds.Contains(x.TeamId)).Select(x =>
new CapacityDetailsModel.ScenarioCalendarRowResource()
{
Id = x.Id,
ExpedentureCategoryId = x.ExpedentureCategoryId,
Name = x.Name,
QuantityValues = new decimal[model.Headers.Count],
SpreadVal = new CapacityDetailsModel.Spread[model.Headers.Count],
QuantityTotalResValue = new decimal[model.Headers.Count],
GrandTotalCost = 0M,
GrandTotalQuantity = 0M,
IsActiveEmployee = x.IsActiveEmployee,
TeamId = x.TeamId
}))
}).ToList();
foreach (var ec in d)
{
var uomMultiplier = Utils.GetUOMMultiplier(remainingExpCats, allUoms, ec.ExpCatId.Value, model.IsUOMHours);
var UoMVal = remainingExpCats.First(x => x.Id == ec.ExpCatId).UOM.UOMValue * uomMultiplier;
ec.QuantityResValue = UoMVal;
var monthQuantity = 0.0M;
var monthQuantityRes = 0.0M;
for(var colIndex = 0; colIndex < model.Headers.Count; colIndex++)
{
if (model.Headers[colIndex].IsMonth){
ec.QuantityTotalResValue[colIndex] = monthQuantity;
ec.Resources.ForEach(r => r.QuantityTotalResValue[colIndex] = (r.IsActiveEmployee ? monthQuantityRes : 0));
monthQuantity = 0.0M;
monthQuantityRes = 0.0M;
}else{
monthQuantity += UoMVal * ec.Resources.Where(r=>r.IsActiveEmployee).Count();
monthQuantityRes += UoMVal;
ec.QuantityTotalResValue[colIndex] = UoMVal * ec.Resources.Where(r=>r.IsActiveEmployee).Count();
ec.Resources.ForEach(r => r.QuantityTotalResValue[colIndex] = (r.IsActiveEmployee ? UoMVal : 0));
}
//ec.SpreadVal[colIndex] = ec.QuantityValues[colIndex] == ec.QuantityTotalResValue[colIndex] ? CapacityDetailsModel.Spread.Equal :
// ec.QuantityValues[colIndex] > ec.QuantityTotalResValue[colIndex] ? CapacityDetailsModel.Spread.Over :
// ec.QuantityValues[colIndex] < r.QuantityTotalResValue[colIndex] ? CapacityDetailsModel.Spread.Less : CapacityDetailsModel.Spread.Notspecified);
ec.Resources.ForEach(r => r.SpreadVal[colIndex] = compareValues(r.QuantityValues[colIndex] , r.QuantityTotalResValue[colIndex]) ==0 ? CapacityDetailsModel.Spread.Equal :
compareValues(r.QuantityValues[colIndex] , r.QuantityTotalResValue[colIndex]) > 0 ? CapacityDetailsModel.Spread.Over :
compareValues(r.QuantityValues[colIndex] , r.QuantityTotalResValue[colIndex]) < 0 ? CapacityDetailsModel.Spread.Less : CapacityDetailsModel.Spread.Notspecified);
}
}
totalsList.AddRange(d);
#endregion
#region set capacity row values as sum of each expenditure category capacities
foreach (var bottomExpCatRow in totalsList.Where(t => CapacityDetailsModel.RowType.BottomCategory.Equals(t.RowType)))
{
if (bottomExpCatRow.QuantityTotalResValue != null)
for (var weekIndex = 0; weekIndex < bottomExpCatRow.QuantityTotalResValue.Length; weekIndex++)
{
capacityRow.QuantityValues[weekIndex] += bottomExpCatRow.QuantityTotalResValue[weekIndex];
}
}
#endregion
model.Calendar.AddRange(totalsList);
#region Fill Vacation, trainig and loan out weekly allocations for each resource
decimal monthResVacation = 0.0M;
decimal monthResTraining = 0.0M;
foreach (var res in model.AllResources)
{
var uomMultiplier = Utils.GetUOMMultiplier(allExpCats, allUoms,
res.ExpedentureCategoryId ?? Guid.Empty,
model.IsUOMHours);
for (int colIndex = 0; colIndex < itemsCount; colIndex++) //(var column1 in expCat.Value)
{
var date = epoch.AddSeconds(model.Headers[colIndex].Milliseconds/1000);
// if item is a new week
if (!model.Headers[colIndex].IsMonth)
{
var vacationQuantityValue = allResourceVacations.Where(t => t.PeopleResourceId == res.Id &&
t.WeekEndingDate <= date &&
t.WeekEndingDate >= date.AddDays(-6))
.Sum(s => s.HoursOff) * uomMultiplier;
res.VacationQuantityValues[colIndex] = vacationQuantityValue;
monthResVacation += vacationQuantityValue;
var trainingQuantityValue = allResourceTrainings.Where(t => t.PeopleResourceId == res.Id &&
t.WeekEndingDate <= date &&
t.WeekEndingDate >= date.AddDays(-6))
.Sum(s => s.HoursOff) * uomMultiplier;
res.TrainingQuantityValues[colIndex] = trainingQuantityValue;
monthResTraining += trainingQuantityValue;
}
else
{
res.VacationQuantityValues[colIndex] = monthResVacation;
monthResVacation = 0.0M;
res.TrainingQuantityValues[colIndex] = monthResTraining;
monthResTraining = 0.0M;
}
}
}
#endregion
return model;
//return null;
}
private int compareValues(decimal val1, decimal val2)
{
var val1_ = decimal.Round( val1, 3);
var val2_ = decimal.Round(val2, 3);
if ((-0.005m > (val1_ - val2_)))
return -1;
else
if ((0.005m < (val1_ - val2_)))
return 1;
else
return 0;
}
public void BuildHeaders(CapacityDetailsModel model, List<DateTime> gridHeaders)
{
model.Headers = new List<CapacityDetailsModel.Header>((int)(gridHeaders.Count * 1.25));
var prevMonth = string.Empty;
var prevYear = string.Empty;
var monthIndex = -1;
var yearIndex = -1;
CapacityDetailsModel.Header monthColumn = null;
CapacityDetailsModel.Header yearColumn = 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"); //("MMMM yyyy");
var gridHeaderYearTitle = gridHeader.ToString("yyyy");
if (!prevMonth.Equals(gridHeaderTitle))
{
if (monthColumn != null)
{
model.Headers.Add(monthColumn);
yearColumn.SpanCount++; // model.Headers.Count - 1;
}
monthColumn = new CapacityDetailsModel.Header()
{
Show = true,
Milliseconds = (long)gridHeader.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds,
MonthIndex = ++monthIndex,
IsMonth = true,
Title = gridHeaderTitle,
Year = gridHeaderYearTitle,
Weeks = new List<int>()
};
}
if (!prevYear.Equals(gridHeaderYearTitle))
{
if (yearColumn != null)
{
model.YearHeaders.Add(yearColumn);
}
yearColumn = new CapacityDetailsModel.Header()
{
Show = true,
Milliseconds = (long)gridHeader.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds,
YearIndex = ++yearIndex,
IsMonth = false,
Title = gridHeaderYearTitle,
//Weeks = new List<int>()
};
}
var weekHeader = new CapacityDetailsModel.Header()
{
IsMonth = false,
Milliseconds = (long)gridHeader.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds,
MonthIndex = monthColumn.MonthIndex,
Title = gridHeader.ToString("dd") //ToShortDateString()
};
model.Headers.Add(weekHeader);
monthColumn.Weeks.Add(model.Headers.Count - 1);
monthColumn.Milliseconds = weekHeader.Milliseconds;
yearColumn.Milliseconds = weekHeader.Milliseconds;
prevMonth = gridHeaderTitle;
prevYear = gridHeaderYearTitle;
}
if (monthColumn != null)
{
model.Headers.Add(monthColumn);
yearColumn.SpanCount++;
}
if (yearColumn != null)
{
model.YearHeaders.Add(yearColumn);
}
}
private decimal GetProjectNeedMultiplier(Guid scenarioId, List<Guid> calendarTeamIds, Dictionary<Guid, List<Team2Scenario>> teams2scenarios)
{
if (!teams2scenarios.ContainsKey(scenarioId))
return 1;
decimal mul = 0.0M;
foreach (Team2Scenario t2s in teams2scenarios[scenarioId])
{
foreach (Guid teamId in calendarTeamIds)
{
if (t2s.TeamId == teamId)
mul += (decimal)t2s.Allocation;
}
}
return mul / 100;
}
//[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]
[AreaSecurityAttribute(area = Areas.Scenarios, level = AccessLevel.Write)]
public ActionResult SaveChanges(SaveCapacityDetailsChangesModel model)
{
//if (model.ScenarioId != Guid.Empty && ContentLocker.IsLock("Scenario", model.ScenarioId.ToString(), User.Identity.Name))
// return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
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 == changedExpCat.ScenarioId
&& x.ExpenditureCategoryId == changedExpCat.Id).ToList();
foreach (var resource in changedExpCat.Resources)
{
var resourceId = resource.Id;
if (resource.IsRemoved)
{
var recourcesToDelete = context.PeopleResourceAllocations.Where(x => x.PeopleResourceId == resource.Id && x.ScenarioId == changedExpCat.ScenarioId && x.ExpenditureCategoryId == changedExpCat.Id).ToList();
recourcesToDelete.ForEach(x => context.PeopleResourceAllocations.Remove(x));
recourcesToDelete.ForEach(x => context.Entry(x).State = System.Data.Entity.EntityState.Deleted);
}
else
{
var allocateResourceIdsUpdated = new List<Guid>();
foreach (var changedResource in resource.Values)
{
//if (changedResource.Id.HasValue)
{
var date = epoch.AddSeconds(changedResource.Milliseconds / 1000);
var allocatedResource = (from c in resourceAllocations
where c.WeekEndingDate == date && c.PeopleResourceId == resourceId
select c).FirstOrDefault();
if (changedResource.Quantity <= 0)
{
if (allocatedResource != null)
context.Entry(allocatedResource).State = System.Data.Entity.EntityState.Deleted;
continue;
}
if (allocatedResource == null)
{
allocatedResource = context.PeopleResourceAllocations.Create();
allocatedResource.Id = Guid.NewGuid();
allocatedResource.ExpenditureCategoryId = changedExpCat.Id;
allocatedResource.PeopleResourceId = resourceId;
allocatedResource.ScenarioId = changedExpCat.ScenarioId;
allocatedResource.WeekEndingDate = date;
context.Entry(allocatedResource).State = System.Data.Entity.EntityState.Added;
}
else
{
context.Entry(allocatedResource).State = System.Data.Entity.EntityState.Modified;
}
allocatedResource.Quantity = changedResource.Quantity / uomMultiplier;
}
//var recourcesToDelete = context.PeopleResourceAllocations.Where(x => allocateResourceIdsUpdated.Contains(x.Id)).ToList();
//recourcesToDelete.ForEach(x => context.PeopleResourceAllocations.Remove(x));
//recourcesToDelete.ForEach(x => context.Entry(x).State = System.Data.Entity.EntityState.Deleted);
}
}
}
}
}
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);
}
}
}