943 lines
38 KiB
C#
943 lines
38 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Data.Entity;
|
|
using System.Data.Entity.Infrastructure;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Web;
|
|
using System.Web.Mvc;
|
|
using EnVisage;
|
|
using EnVisage.Code;
|
|
using EnVisage.Code.BLL;
|
|
using EnVisage.Code.HtmlHelpers;
|
|
using EnVisage.Models;
|
|
using jQuery.DataTables.Mvc;
|
|
using EnVisage.App_Start;
|
|
using Microsoft.AspNet.Identity;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using FileHelpers;
|
|
using System.Web.Script.Serialization;
|
|
using EnVisage.Code.Cache;
|
|
|
|
namespace EnVisage.Controllers
|
|
{
|
|
[Authorize]
|
|
public class ProjectController : BaseController
|
|
{
|
|
/// <summary>
|
|
/// GET: /Project/
|
|
/// </summary>
|
|
/// <returns>Empty view</returns>
|
|
[HttpGet]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Read)]
|
|
public ActionResult Index()
|
|
{
|
|
if (!HtmlHelpers.CheckSecurityObjectPermission(null, Areas.Projects, AccessLevel.Read))
|
|
return Redirect("/");
|
|
ViewBag.Source = PagePreferencesList.PagePreferencesSource.Project_Index;
|
|
return View();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns JSON project list with filters and sort for jQuery DataTables
|
|
/// </summary>
|
|
[HttpPost]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Read)]
|
|
public JsonResult Index(JQueryDataTablesModel jQueryDataTablesModel)
|
|
{
|
|
int totalRecordCount;
|
|
int searchRecordCount;
|
|
|
|
var clients = GetProjects(startIndex: jQueryDataTablesModel.iDisplayStart,
|
|
pageSize: jQueryDataTablesModel.iDisplayLength, sortedColumns: jQueryDataTablesModel.GetSortedColumns(),
|
|
totalRecordCount: out totalRecordCount, searchRecordCount: out searchRecordCount, searchString: jQueryDataTablesModel.sSearch);
|
|
|
|
return this.DataTablesJson(items: clients,
|
|
totalRecords: totalRecordCount,
|
|
totalDisplayRecords: searchRecordCount,
|
|
sEcho: jQueryDataTablesModel.sEcho);
|
|
|
|
}
|
|
private string GetJson(Scenario scenario){
|
|
return "";
|
|
}
|
|
|
|
private IList<ProjectListModel> GetProjects(int startIndex,
|
|
int pageSize,
|
|
ReadOnlyCollection<SortedColumn> sortedColumns,
|
|
out int totalRecordCount,
|
|
out int searchRecordCount,
|
|
string searchString)
|
|
{
|
|
var principals = GetUserPrincipals();
|
|
var projectAccesses = new ProjectAccessCache().Value.Where(x => principals.Contains(x.PrincipalId));
|
|
List<Guid> availableProjects = new List<Guid>();
|
|
HashSet<Guid> writeEnabledProjects = new HashSet<Guid>();
|
|
foreach (var p in projectAccesses)
|
|
{
|
|
availableProjects.Add(p.ProjectId);
|
|
if(p.Write == 1)
|
|
writeEnabledProjects.Add(p.ProjectId);
|
|
}
|
|
|
|
var query = from p in DbContext.Projects
|
|
join parts in DbContext.Projects on p.Id equals parts.ParentProjectId into projectParts
|
|
where availableProjects.Contains(p.Id) && p.ParentProjectId == null
|
|
select new ProjectListModel()
|
|
{
|
|
Id = p.Id,
|
|
ProjectName = p.Name,
|
|
ProjectNumber = p.ProjectNumber ?? string.Empty,
|
|
Status = p.Status.Name ?? string.Empty,
|
|
Classification = p.Type.Name ?? string.Empty,
|
|
Client = p.Client.Name ?? string.Empty,
|
|
Company = p.Company.Name ?? string.Empty,
|
|
ScenariosCount = p.Scenarios.Count(),
|
|
Priority = p.Priority,
|
|
WritePermissionEnabledForCurrentUser = writeEnabledProjects.Contains(p.Id),
|
|
Teams = p.Team2Project.Select(t => t.Team).Select(t => t.Name),
|
|
ActiveScenario = p.Scenarios.Where(s => s.Type == (int)ScenarioType.Portfolio && s.Status == (int)ScenarioStatus.Active).Select(x => x.Id.ToString() + "//" + x.Name).FirstOrDefault(),
|
|
InactiveScenarios = p.Scenarios.Where(s => s.Type == (int)ScenarioType.Portfolio && s.Status == (int)ScenarioStatus.Inactive).Select(x => x.Id.ToString() + "//" + x.Name),
|
|
HasChildren = p.HasChildren,
|
|
ProjectParts = projectParts.Select(pp =>
|
|
new ProjectPartListModel()
|
|
{
|
|
Id = pp.Id,
|
|
ProjectName = pp.Name,
|
|
ProjectNumber = pp.ProjectNumber ?? string.Empty,
|
|
Status = pp.Status.Name ?? string.Empty,
|
|
Classification = pp.Type.Name ?? string.Empty,
|
|
Client = pp.Client.Name ?? string.Empty,
|
|
Company = pp.Company.Name ?? string.Empty,
|
|
ScenariosCount = pp.Scenarios.Count(),
|
|
Priority = pp.Priority,
|
|
WritePermissionEnabledForCurrentUser = writeEnabledProjects.Contains(pp.Id),
|
|
Teams = pp.Team2Project.Select(t => t.Team).Select(t => t.Name),
|
|
ActiveScenario = pp.Scenarios.Where(s => s.Type == (int)ScenarioType.Portfolio && s.Status == (int)ScenarioStatus.Active).Select(x => x.Id.ToString() + "//" + x.Name).FirstOrDefault(),
|
|
InactiveScenarios = pp.Scenarios.Where(s => s.Type == (int)ScenarioType.Portfolio && s.Status == (int)ScenarioStatus.Inactive).Select(x => x.Id.ToString() + "//" + x.Name)
|
|
}
|
|
).ToList()
|
|
|
|
//For debugging only
|
|
//ProjectParts = new List<ProjectPartListModel>(){
|
|
// new ProjectPartListModel()
|
|
// {
|
|
// Id = p.Id,
|
|
// ProjectName = p.Name,
|
|
// ProjectNumber = p.ProjectNumber ?? string.Empty,
|
|
// Status = p.Status.Name ?? string.Empty,
|
|
// Classification = p.Type.Name ?? string.Empty,
|
|
// Client = p.Client.Name ?? string.Empty,
|
|
// Company = p.Company.Name ?? string.Empty,
|
|
// ScenariosCount = p.Scenarios.Count(),
|
|
// Priority = p.Priority,
|
|
// WritePermissionEnabledForCurrentUser = writeEnabledProjects.Contains(p.Id),
|
|
// Teams = p.Team2Project.Select(t => t.Team).Select(t => t.Name),
|
|
// ActiveScenario = p.Scenarios.Where(s => s.Type == (int)ScenarioType.Portfolio && s.Status == (int)ScenarioStatus.Active).Select(x => x.Id.ToString() + "//" + x.Name).FirstOrDefault(),
|
|
// InactiveScenarios = p.Scenarios.Where(s => s.Type == (int)ScenarioType.Portfolio && s.Status == (int)ScenarioStatus.Inactive).Select(x => x.Id.ToString() + "//" + x.Name)
|
|
// }
|
|
//}
|
|
};
|
|
|
|
//filter
|
|
if (!string.IsNullOrWhiteSpace(searchString))
|
|
{
|
|
string searchStringLow = searchString.ToLower();
|
|
query = query.Where(c => c.ProjectName.ToLower().Contains(searchStringLow) || c.ProjectNumber.ToLower().Contains(searchStringLow) ||
|
|
c.ActiveScenario.ToLower().Contains(searchStringLow) || c.ProjectParts.Any(pp => pp.ProjectName.Contains(searchStringLow)) /*|| c.Teams.Any(t => t.Contains(searchStringLow))*/);
|
|
}
|
|
|
|
//sort
|
|
foreach (var sortedColumn in sortedColumns)
|
|
{
|
|
switch (sortedColumn.PropertyName)
|
|
{
|
|
case "Id":
|
|
if (sortedColumn.Direction == SortingDirection.Ascending)
|
|
query = query.OrderBy(p => p.Id);
|
|
else
|
|
query = query.OrderByDescending(p => p.Id);
|
|
break;
|
|
case "ActiveScenario":
|
|
if (sortedColumn.Direction == SortingDirection.Ascending)
|
|
query = query.OrderBy(p => p.ActiveScenario);
|
|
else
|
|
query = query.OrderByDescending(p => p.ActiveScenario);
|
|
break;
|
|
case "ProjectNumber":
|
|
if (sortedColumn.Direction == SortingDirection.Ascending)
|
|
query = query.OrderBy(p => p.ProjectNumber);
|
|
else
|
|
query = query.OrderByDescending(p => p.ProjectNumber);
|
|
break;
|
|
case "Status":
|
|
if (sortedColumn.Direction == SortingDirection.Ascending)
|
|
query = query.OrderBy(p => p.Status);
|
|
else
|
|
query = query.OrderByDescending(p => p.Status);
|
|
break;
|
|
case "Priority":
|
|
if (sortedColumn.Direction == SortingDirection.Ascending)
|
|
query = query.OrderBy(p => p.Priority);
|
|
else
|
|
query = query.OrderByDescending(p => p.Priority);
|
|
break;
|
|
case "Classification":
|
|
if (sortedColumn.Direction == SortingDirection.Ascending)
|
|
query = query.OrderBy(p => p.Classification);
|
|
else
|
|
query = query.OrderByDescending(p => p.Classification);
|
|
break;
|
|
default:
|
|
if (sortedColumn.Direction == SortingDirection.Ascending)
|
|
query = query.OrderBy(p => p.ProjectName);
|
|
else
|
|
query = query.OrderByDescending(p => p.ProjectName);
|
|
break;
|
|
}
|
|
}
|
|
|
|
totalRecordCount = DbContext.Projects.Where(p => availableProjects.Contains(p.Id)).Count();
|
|
searchRecordCount = query.Count();
|
|
return query.Skip(startIndex).Take(pageSize).ToList();
|
|
}
|
|
|
|
|
|
// GET: /Project/Details/5
|
|
[HttpGet]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Read)]
|
|
public ActionResult Details(Guid? id)
|
|
{
|
|
if (id == null || id == Guid.Empty)
|
|
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
|
|
|
if (!HtmlHelpers.CheckProjectPermission(null, id.Value, AccessLevel.Read))
|
|
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
|
|
|
|
var model = new ProjectModel();
|
|
try
|
|
{
|
|
var manager = new ProjectManager(DbContext);
|
|
model = (ProjectModel)manager.Load(id) ?? new ProjectModel();
|
|
if (model.Id == Guid.Empty)
|
|
return HttpNotFound();
|
|
}
|
|
catch (BLLException blEx)
|
|
{
|
|
if (blEx.DisplayError)
|
|
SetErrorScript(message: blEx.Message);
|
|
else
|
|
{
|
|
LogException(blEx);
|
|
SetErrorScript();
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
LogException(exception);
|
|
SetErrorScript();
|
|
}
|
|
return PartialView("_details", model);
|
|
}
|
|
|
|
[HttpGet]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Write)]
|
|
public ActionResult Copy(Guid? id)
|
|
{
|
|
if (id != null && id != Guid.Empty)
|
|
if (!HtmlHelpers.CheckProjectPermission(null, id.Value, AccessLevel.Write))
|
|
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
|
|
|
|
var model = new ProjectModel();
|
|
try
|
|
{
|
|
var manager = new ProjectManager(DbContext);
|
|
model = (ProjectModel)manager.Load(id) ?? new ProjectModel();
|
|
|
|
var projectStatus = DbContext.Status.FirstOrDefault(x => x.Id == model.StatusId);
|
|
if (projectStatus != null)
|
|
{
|
|
if (projectStatus.Probability100)
|
|
model.Probability = 100;
|
|
ViewBag.IsProbability100 = projectStatus.Probability100;
|
|
}
|
|
else
|
|
{
|
|
ViewBag.IsProbability100 = false;
|
|
}
|
|
|
|
var statuses = DbContext.Status.Select(x => new { Id = x.Id, Probability100 = x.Probability100 }).ToList();
|
|
ViewBag.Statuses = new JavaScriptSerializer().Serialize(statuses);
|
|
}
|
|
catch (BLLException blEx)
|
|
{
|
|
if (blEx.DisplayError)
|
|
SetErrorScript(message: blEx.Message);
|
|
else
|
|
{
|
|
LogException(blEx);
|
|
SetErrorScript();
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
LogException(exception);
|
|
SetErrorScript();
|
|
}
|
|
model.SaveAsCopy = true;
|
|
return Edit(model);
|
|
}
|
|
|
|
// GET: /Project/Edit/5
|
|
[HttpGet]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Write)]
|
|
public ActionResult Edit(Guid? id)
|
|
{
|
|
if(id != null && id != Guid.Empty)
|
|
if (!HtmlHelpers.CheckProjectPermission(null, id.Value, AccessLevel.Write))
|
|
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
|
|
|
|
var model = new ProjectModel();
|
|
try
|
|
{
|
|
var manager = new ProjectManager(DbContext);
|
|
model = (ProjectModel)manager.Load(id) ?? new ProjectModel();
|
|
if (id == null || Guid.Empty.Equals(id))
|
|
{
|
|
model.ClientId = Guid.Empty;
|
|
model.Priority = 1;
|
|
}
|
|
var statuses = DbContext.Status.Select(x => new { Id = x.Id, Probability100 = x.Probability100 }).ToList();
|
|
ViewBag.Statuses = new JavaScriptSerializer().Serialize(statuses);
|
|
}
|
|
catch (BLLException blEx)
|
|
{
|
|
if (blEx.DisplayError)
|
|
SetErrorScript(message: blEx.Message);
|
|
else
|
|
{
|
|
LogException(blEx);
|
|
SetErrorScript();
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
LogException(exception);
|
|
SetErrorScript();
|
|
}
|
|
return View(model);
|
|
}
|
|
|
|
// POST: /Project/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.Projects, level = AccessLevel.Write)]
|
|
public ActionResult Edit(ProjectModel model)
|
|
{
|
|
if (model == null || ContentLocker.IsLock("Project", model.Id.ToString(), User.Identity.Name))
|
|
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
|
|
|
if (model.Id != Guid.Empty)
|
|
if (!HtmlHelpers.CheckProjectPermission(null, model.Id, AccessLevel.Write))
|
|
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
|
|
|
|
#region trim model and remove incorrect values
|
|
model.TrimStringProperties();
|
|
// if user clicked "Generate Template" then save a project as new and mark it as IsTemplate=true
|
|
var isCreateCopy = model.SaveAsCopy;
|
|
var oldId = Guid.Empty;
|
|
var model2Save = (ProjectModel)model.Clone();
|
|
if (isCreateCopy)
|
|
{
|
|
oldId = model.Id;
|
|
model2Save.Parts = model.Parts.Select(p => p.Clone()).ToList();
|
|
model2Save.Id = Guid.Empty;
|
|
model2Save.Name += " - Copy";
|
|
model2Save.Parts.ToList().ForEach(p => p.Id = Guid.Empty);
|
|
model2Save.Parts.ToList().ForEach(p => p.ParentProjectId = Guid.Empty);
|
|
}
|
|
model2Save.ClientId = null;
|
|
var revalidationRequired = false;
|
|
for (var i = 0; i < model2Save.Parts.Count; i++)
|
|
{
|
|
if (model2Save.Parts[i].DeletedPart)
|
|
{
|
|
model.Parts.RemoveAt(i);
|
|
revalidationRequired = true;
|
|
}
|
|
}
|
|
foreach (var part in model2Save.Parts)
|
|
{
|
|
if (part.InternalContacts != null)
|
|
part.InternalContacts.RemoveAll(t => t == Guid.Empty);
|
|
if (part.ExternalContacts != null)
|
|
part.ExternalContacts.RemoveAll(t => t == Guid.Empty);
|
|
}
|
|
//TODO: temporary solution, we need to check for Guid.Empty.Equals(model2Save.Id). Should be replaced when fix the bug in BaseManager.Save method.
|
|
var isNew = Guid.Empty.Equals(model2Save.Id);
|
|
if (revalidationRequired)
|
|
{
|
|
ModelState.Clear();
|
|
TryValidateModel(model);
|
|
}
|
|
#endregion
|
|
|
|
if (ModelState.IsValid)
|
|
{
|
|
try
|
|
{
|
|
var manager = new ProjectManager(DbContext);
|
|
var newProject = manager.Save(model2Save);
|
|
DbContext.SaveChanges();
|
|
var partIds = DbContext.Projects.Where(t => t.ParentProjectId == newProject.Id).Select(t=>t.Id).ToArray();
|
|
//Give user Full Access permissions to the new project
|
|
var teamIds = new List<Guid>();
|
|
foreach (var part in model2Save.Parts)
|
|
{
|
|
if (part.AssignedTeams != null)
|
|
teamIds.AddRange(part.AssignedTeams);
|
|
}
|
|
var existingUsersPermissions =
|
|
DbContext.ProjectAccesses.Where(t => partIds.Contains(t.ProjectId) || t.ProjectId == newProject.Id)
|
|
.Select(t => new {t.ProjectId, t.PrincipalId}).ToList();
|
|
var users = (from c in DbContext.User2Team where teamIds.Contains(c.TeamId) select c.UserId).Distinct().ToList();
|
|
if (!users.Contains(User.Identity.GetUserId(), StringComparer.OrdinalIgnoreCase))
|
|
users.Add(User.Identity.GetUserId());
|
|
foreach (var contributor in users)
|
|
{
|
|
if (!existingUsersPermissions.Any(t => t.PrincipalId == new Guid(contributor) && t.ProjectId == newProject.Id))
|
|
{
|
|
DbContext.ProjectAccesses.Add(new ProjectAccess()
|
|
{
|
|
PrincipalId = new Guid(contributor),
|
|
ProjectId = newProject.Id,
|
|
Read = 1,
|
|
Write = 1
|
|
});
|
|
}
|
|
foreach (var partId in partIds)
|
|
{
|
|
if (!existingUsersPermissions.Any(t => t.PrincipalId == new Guid(contributor) && t.ProjectId == partId))
|
|
{
|
|
DbContext.ProjectAccesses.Add(new ProjectAccess()
|
|
{
|
|
PrincipalId = new Guid(contributor),
|
|
ProjectId = partId,
|
|
Read = 1,
|
|
Write = 1
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isNew)
|
|
{
|
|
#region Create Actuals scenario
|
|
if (!isCreateCopy)
|
|
{
|
|
var scenario = new Scenario
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
Name = "ACTUALS",
|
|
ParentId = newProject.Id,
|
|
Type = ScenarioType.Actuals.GetHashCode(),
|
|
StartDate = DateTime.Now,
|
|
Color = "",
|
|
ProjectedRevenue = 0
|
|
};
|
|
DbContext.Scenarios.Add(scenario);
|
|
}
|
|
#endregion
|
|
|
|
#region Copy scenarios and referenced scenario details
|
|
|
|
//if (model2Save.TemplateId.HasValue && !Guid.Empty.Equals(model2Save.TemplateId))
|
|
//{
|
|
// oldId = model2Save.TemplateId.Value;
|
|
// var scenarios = DbContext.Scenarios.Where(t => t.ParentId == oldId).ToList();
|
|
|
|
// CopyScenarios(scenarios, newProject.Id);
|
|
//}
|
|
|
|
if (isCreateCopy)
|
|
{
|
|
if (!model2Save.HasChildren)
|
|
{
|
|
var scenarios = DbContext.Scenarios.Where(t => t.ParentId == oldId).ToList();
|
|
CopyScenarios(scenarios, newProject.Id);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
foreach (var part in model2Save.Parts)
|
|
{
|
|
var scenarios = DbContext.Scenarios.Where(t => t.ParentId == part.OldId).ToList();
|
|
CopyScenarios(scenarios, part.Id);
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
|
|
DbContext.SaveChanges();
|
|
new ProjectAccessCache().Invalidate();
|
|
ContentLocker.RemoveLock("Project", model.Id.ToString(), User.Identity.Name);
|
|
if (!isCreateCopy)
|
|
{
|
|
if (model2Save.ContinueToScenarios)
|
|
{
|
|
if(model.HasChildren)
|
|
return RedirectToAction("Edit", new { @id = newProject.Id, @ptab = "scenarios" });
|
|
else
|
|
return RedirectToAction("Edit", new { @id = newProject.Id, @ptab = "newscenario" });
|
|
}
|
|
else
|
|
{
|
|
return RedirectToAction("Index");
|
|
}
|
|
}
|
|
else
|
|
return RedirectToAction("Edit", "Project", new { id = newProject.Id });
|
|
}
|
|
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)
|
|
var statuses = DbContext.Status.Select(x => new { Id = x.Id, Probability100 = x.Probability100 }).ToList();
|
|
ViewBag.Statuses = new JavaScriptSerializer().Serialize(statuses);
|
|
return View(model);
|
|
}
|
|
|
|
private void CopyScenarios(IEnumerable<Scenario> scenarios, Guid newProjectId)
|
|
{
|
|
foreach (var currScenario in scenarios)
|
|
{
|
|
var currDetails = DbContext.ScenarioDetail.Where(
|
|
t => t.ParentID == currScenario.Id).AsNoTracking().ToList().OrderBy(t => t.ExpenditureCategoryId).ThenBy(t => t.WeekOrdinal);
|
|
var newScenario = new Scenario
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
ParentId = newProjectId,
|
|
Type = currScenario.Type,
|
|
Name = currScenario.Name,
|
|
ProjectedRevenue = currScenario.ProjectedRevenue,
|
|
ExpectedGrossMargin = currScenario.ExpectedGrossMargin,
|
|
CalculatedGrossMargin = currScenario.CalculatedGrossMargin,
|
|
CGSplit = currScenario.CGSplit,
|
|
EFXSplit = currScenario.EFXSplit,
|
|
Duration = currScenario.Duration,
|
|
TDDirectCosts = currScenario.TDDirectCosts,
|
|
BUDirectCosts = currScenario.BUDirectCosts,
|
|
Shots = currScenario.Shots,
|
|
TDRevenueShot = currScenario.TDRevenueShot,
|
|
BURevenueShot = currScenario.BURevenueShot,
|
|
LastUpdate = DateTime.Now,
|
|
Status = currScenario.Status,
|
|
UseLMMargin = currScenario.UseLMMargin,
|
|
ExpectedGrossMargin_LM = currScenario.ExpectedGrossMargin_LM,
|
|
CalculatedGrossMargin_LM = currScenario.CalculatedGrossMargin_LM,
|
|
TDDirectCosts_LM = currScenario.TDDirectCosts_LM,
|
|
BUDirectCosts_LM = currScenario.BUDirectCosts_LM,
|
|
BURevenueShot_LM = currScenario.BURevenueShot_LM,
|
|
EntryTimeStamp = DateTime.Now,
|
|
Actuals_BUDirectCosts = currScenario.Actuals_BUDirectCosts,
|
|
Actuals_BUDirectCosts_LM = currScenario.Actuals_BUDirectCosts_LM,
|
|
FreezeRevenue = currScenario.FreezeRevenue,
|
|
GrowthScenario = currScenario.GrowthScenario,
|
|
TemplateId = currScenario.TemplateId,
|
|
Color = currScenario.Color,
|
|
ProjectedExpense = currScenario.ProjectedExpense,
|
|
StartDate = currScenario.StartDate,
|
|
EndDate = currScenario.EndDate,
|
|
ShotStartDate = currScenario.ShotStartDate,
|
|
SystemAttributeObjectID = currScenario.SystemAttributeObjectID
|
|
};
|
|
DbContext.Scenarios.Add(newScenario);
|
|
|
|
foreach (var detail in currDetails)
|
|
{
|
|
var newDetailItem = new ScenarioDetail
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
ExpenditureCategoryId = detail.ExpenditureCategoryId,
|
|
ParentID = newScenario.Id,
|
|
Quantity = detail.Quantity,
|
|
Cost = detail.Cost,
|
|
WeekOrdinal = detail.WeekOrdinal,
|
|
WeekEndingDate = detail.WeekEndingDate,
|
|
LastUpdate = DateTime.Now
|
|
};
|
|
|
|
DbContext.ScenarioDetail.Add(newDetailItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
[HttpPost]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Write)]
|
|
public ActionResult AddPart(ProjectPartModel model, int count)
|
|
{
|
|
try
|
|
{
|
|
if (ContentLocker.IsLock("Project", (model.ParentProjectId ?? Guid.Empty).ToString(), User.Identity.Name))
|
|
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
|
|
|
if (model.ParentProjectId.HasValue && model.ParentProjectId != Guid.Empty)
|
|
if (!HtmlHelpers.CheckProjectPermission(null, model.ParentProjectId.Value, AccessLevel.Write))
|
|
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
|
|
//var ticks = DateTime.UtcNow.Ticks;
|
|
//var nestedObject = Activator.CreateInstance(typeof(ProjectModel));
|
|
//var partial = Html.EditorFor(x => nestedObject).ToHtmlString().JsEncode();
|
|
//partial = partial.Replace("id=\\\"nestedObject", "id=\\\"" + collectionProperty + "_" + ticks + "_");
|
|
//partial = partial.Replace("name=\\\"nestedObject", "name=\\\"" + collectionProperty + "[" + ticks + "]");
|
|
|
|
return PartialView("~/Views/Shared/EditorTemplates/ProjectPartModel.cshtml", model);
|
|
//return Json(new
|
|
// {
|
|
// html=v.ToString()
|
|
// });
|
|
}
|
|
catch (BLLException blEx) // handle any system specific error
|
|
{
|
|
// display error message if required
|
|
if (blEx.DisplayError)
|
|
SetErrorScript(message: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 EmptyResult();
|
|
}
|
|
|
|
// GET: /Project/Delete/5
|
|
[HttpGet]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Write)]
|
|
public ActionResult Delete(Guid? id)
|
|
{
|
|
if (id == null || id == Guid.Empty)
|
|
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
|
|
|
if (!HtmlHelpers.CheckProjectPermission(null, id.Value, AccessLevel.Write))
|
|
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
|
|
|
|
var model = new ProjectModel();
|
|
try
|
|
{
|
|
var manager = new ProjectManager(DbContext);
|
|
model = (ProjectModel)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: /Project/Delete/5
|
|
[HttpPost, ActionName("Delete")]
|
|
[ValidateAntiForgeryToken]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Write)]
|
|
public ActionResult Delete(ProjectModel model)
|
|
{
|
|
if (ContentLocker.IsLock("Project", model.Id.ToString(), User.Identity.Name))
|
|
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
|
|
|
|
if (!HtmlHelpers.CheckProjectPermission(null, model.Id, AccessLevel.Write))
|
|
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
|
|
|
|
var manager = new ProjectManager(DbContext);
|
|
var dbObj = manager.Load(model.Id, false);
|
|
if (dbObj == null)
|
|
return HttpNotFound();
|
|
|
|
(DbContext as IObjectContextAdapter).ObjectContext.ExecuteStoreCommand(string.Format("exec sp_DeleteProject '{0}'", dbObj.Id));
|
|
DbContext.SaveChanges();
|
|
|
|
ContentLocker.RemoveLock("Project", dbObj.Id.ToString(), User.Identity.Name);
|
|
return RedirectToAction("Index");
|
|
}
|
|
|
|
[HttpGet]
|
|
[AreaSecurityAttribute(area = Areas.ImportActuals, level = AccessLevel.Read)]
|
|
public ActionResult ImportActuals(Guid? id)
|
|
{
|
|
return View();
|
|
}
|
|
|
|
// POST: /Project/Import/5
|
|
[HttpPost, ActionName("ImportActuals")]
|
|
[AreaSecurityAttribute(area = Areas.ImportActuals, level = AccessLevel.Write)]
|
|
public ActionResult ImportActuals(HttpPostedFileBase fileUpload)
|
|
{
|
|
var file = fileUpload;
|
|
|
|
if (file == null || file.ContentLength < 1)
|
|
{
|
|
ModelState.AddModelError("", "File was not loaded");
|
|
return View();
|
|
}
|
|
|
|
using (var reader = new StreamReader(file.InputStream))
|
|
{
|
|
try
|
|
{
|
|
var engine = new FileHelperEngine<EnVisage.Code.ActualsImportRow>();
|
|
ActualsImportRow[] dataRead = engine.ReadStream(reader);
|
|
var importer = new ImportActuals();
|
|
string log = string.Empty;
|
|
ViewBag.ImportResult = importer.ProcessImport(dataRead, Request["firstRowHeaders"] == "on", Request["resetActuals"] == "on", User.Identity.Name, out log);
|
|
ViewBag.ImportLog = log;
|
|
return View();
|
|
}
|
|
catch (Exception c)
|
|
{
|
|
LogException(c);
|
|
ModelState.AddModelError("", c.Message);
|
|
return View();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
[HttpPost]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Write)]
|
|
public ActionResult AddNote(NoteModel model)
|
|
{
|
|
//if (model.ScenarioId != Guid.Empty && ContentLocker.IsLock("Scenarios", 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();
|
|
}
|
|
}
|
|
UriBuilder builder = new UriBuilder(HttpContext.Request.UrlReferrer);
|
|
var query = HttpUtility.ParseQueryString(builder.Query);
|
|
query["ptab"] = "notes";
|
|
builder.Query = query.ToString();
|
|
return Redirect(builder.Uri.AbsoluteUri);
|
|
}
|
|
|
|
[HttpPost]
|
|
[AreaSecurityAttribute(area = Areas.Projects, level = AccessLevel.Write)]
|
|
public ActionResult EditNote(NoteModel model)
|
|
{
|
|
//if (model.ScenarioId != Guid.Empty && ContentLocker.IsLock("Scenarios", 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();
|
|
}
|
|
}
|
|
UriBuilder builder = new UriBuilder(HttpContext.Request.UrlReferrer);
|
|
var query = HttpUtility.ParseQueryString(builder.Query);
|
|
query["ptab"] = "notes";
|
|
builder.Query = query.ToString();
|
|
return Redirect(builder.Uri.AbsoluteUri);
|
|
}
|
|
|
|
// GET: /User/Edit/5
|
|
[AreaSecurityAttribute(area = Areas.Projects, 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.Projects, 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.Projects, 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));
|
|
}
|
|
|
|
[HttpGet]
|
|
public JsonResult LoadExternalContacts(Guid? clientId, string selectControlId)
|
|
{
|
|
return Json(new {
|
|
contacts = LoadContacts(clientId),
|
|
selectControlId = selectControlId
|
|
}
|
|
, JsonRequestBehavior.AllowGet);
|
|
}
|
|
|
|
[HttpGet]
|
|
public JsonResult LoadInternalContacts(Guid? companyId, string selectControlId)
|
|
{
|
|
return Json(new
|
|
{
|
|
contacts = LoadContacts(companyId),
|
|
selectControlId = selectControlId
|
|
}
|
|
, JsonRequestBehavior.AllowGet);
|
|
}
|
|
|
|
private List<ContactModel> LoadContacts(Guid? parentId)
|
|
{
|
|
if (parentId == null || parentId == Guid.Empty)
|
|
return new List<ContactModel>();
|
|
|
|
return DbContext.Contacts.Where(c => c.ParentId == parentId).OrderBy(c => c.LastName).Select(c => new ContactModel
|
|
{
|
|
Id = c.Id,
|
|
ParentId = c.ParentId ?? Guid.Empty,
|
|
FirstName = c.FirstName,
|
|
LastName = c.LastName,
|
|
Type = (ContactType)c.Type,
|
|
Email = c.Email,
|
|
}).ToList();
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
/// <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;
|
|
}
|
|
|
|
}
|
|
}
|