using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Web.Mvc; using EnVisage.Code; using EnVisage.Code.BLL; using EnVisage.Models; using System.Text; using Resources; using System.Threading.Tasks; namespace EnVisage.Controllers { [Authorize] public class CapacityManagementController : BaseController { #region Actions public ActionResult ExportToPDF() { PDFExporter exporter = new PDFExporter { BrowserWidth = 2560 }; byte[] pdfBuffer = exporter.ExportPage(Url.Action("Index", "CapacityManagement", null, this.Request.Url.Scheme), 5, true, Request.Cookies); // send the PDF file to browser FileResult fileResult = new FileContentResult(pdfBuffer, "application/pdf"); fileResult.FileDownloadName = "Prevu-ActivityCalendar-" + DateTime.Today.Month + "-" + DateTime.Today.Day + ".pdf"; return fileResult; } [HttpGet] [AreaSecurity(area = Areas.ActivityCalendar, level = AccessLevel.Read)] public ActionResult Index(Guid? id) { var model = new CapacityPageInitOption(); if (id.HasValue && !Guid.Empty.Equals(id)) { var foundEntity = DbContext.BLL_Objects.FirstOrDefault(x => x.Id.Equals(id.Value)); if (foundEntity != null) { // Get entity type string entityTypeName = foundEntity.EntityName; if (entityTypeName == "Company") { model.EntityType = CapacityPageInitOption.CalendarEntityType.Company; model.EntityId = id.Value; } if (entityTypeName == "View") { model.EntityType = CapacityPageInitOption.CalendarEntityType.View; model.EntityId = id.Value; } if (entityTypeName == "Team") { model.EntityType = CapacityPageInitOption.CalendarEntityType.Team; model.EntityId = id.Value; } if (entityTypeName == "Resource") { model.EntityType = CapacityPageInitOption.CalendarEntityType.Resource; model.EntityId = id.Value; } } } return View(model); } [HttpPost] [ValidateJsonAntiForgeryToken] public ActionResult SaveChanges(ActivityCalendarSaveModel model) { #if DEBUG var watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); Logger.Debug("Start SaveChanges"); #endif model.TrimStringProperties(); #region Debug and tracing var sb = new StringBuilder(); sb.AppendLine("CapacityManagement.SaveChanges method. model:"); model.DebugObjectProperties(sb); Logger.Debug(sb); #endregion #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"SaveChanges Start has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"Start SaveChanges {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif if (ModelState.IsValid) { try { // Perform permissions check var acManager = (new ActivityCalendarManager(DbContext)); if (!acManager.ActivityCalendarSavePermitted(model)) { // AC is in Resource Calendar mode. Current user doesn't have necessary permissions ModelState.AddModelError(string.Empty, Messages.Common_AccessDenied); return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } // Validates incoming data and cleares incorrect data var expenditureTypes = acManager.GetExpenditureTypesFromSaveDataModel(model); var resourcesTeams = acManager.GetTeamsForResourcesFromSaveDataModel(model); var newTeams = acManager.GetNewTeamsFromCalendar(model); var modelValidated = acManager.ValidateCalendarSaveDataModel(model, expenditureTypes, resourcesTeams); using (var transaction = DbContext.Database.BeginTransaction()) { var transactionId = DbContext.GetClientConnectionId(); var userId = SecurityManager.GetUserPrincipal().ToString(); try { //create team add notifications var addedTeams = new List(); var wfMan = new WorkFlowManager(DbContext); #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"SaveChanges model validation and load has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"SaveChanges model validation and load {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif var projectIdScenarioIdDictionary = DbContext.Scenarios.Where(x => newTeams.Keys.Contains(x.Id)).ToDictionary(q => q.ParentId, q => q.Id); foreach (var projectIdScenarioId in projectIdScenarioIdDictionary) { if (!projectIdScenarioId.Key.HasValue) continue; var wfStates = wfMan.GetProjectStates(projectIdScenarioId.Key.Value); //seed state list with NUll so we can loop thru atleast one time and add any notifications that are //not bound by state wfStates.Add(null); foreach (var wfState in wfStates) { var wfstate = wfState != null && string.IsNullOrEmpty(wfState.state) ? wfState.state : null; var teams = newTeams[projectIdScenarioId.Value]; foreach (var t in teams) { if (addedTeams.Contains(t)) continue; addedTeams.Add(t); var who2 = wfMan.GetContactTeamDetails(t, WorkFlowContactNotificationType.TeamScenarioAdd, wfstate); if (who2.Count > 0) who2 = who2.Distinct().ToList(); new NotificationManager(DbContext).CreateTeamAddNotification(who2, projectIdScenarioId.Value, 0, true, wfstate); } } } #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"SaveChanges Team Add notificationsn has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"SaveChanges Team Add notificationsn {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif if (model.SaveAction == SaveAsScenario.New) { // Make scenario copies modelValidated = acManager.CopyScenarios(modelValidated, transactionId); DbContext.BulkSaveChanges(); } #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"SaveChanges Copy Scenarios has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"SaveChanges Copy Scenarios {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif // Update scenarios acManager.UpdateScenarios(modelValidated, expenditureTypes, resourcesTeams, transactionId); DbContext.BulkSaveChanges(); #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"SaveChanges Update Scenarios has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"SaveChanges Update Scenarios All {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif // Update non-project time acManager.UpdateNonProjectTime(modelValidated); DbContext.BulkSaveChanges(); #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"SaveChanges Update Non Project Time has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"SaveChanges Update Non Project Time {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif transaction.Commit(); Task.Run(() => AuditProxy.CommitHistoryChanges(transactionId, userId)); #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"SaveChanges Commit has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"SaveChanges Commit {watch1.ElapsedMilliseconds} ms"); #endif Task.Run(() => AuditProxy.CommitEventChanges(transactionId)); } catch (Exception ex) { transaction.Rollback(); AuditProxy.ClearHistoryChanges(transactionId); AuditProxy.ClearEventChanges(transactionId); LogException(ex); return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } } DoWorkFlowAction(model.WorkFlowActions, this.HttpContext.User.Identity.GetID()); //(new WorkFlowManager(this.DbContext).DoWorkFlowAction(model.WorkFlowActions, this.HttpContext.User.Identity.GetID()); 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] [ValidateJsonAntiForgeryToken] public ActionResult GetActivityCalendar(ActivityCalendarRequestModel model) { if (model == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); try { var acManager = (new ActivityCalendarManager(DbContext)); var acModel = acManager.GetActivityCalendarModel(model); return BigJson(acModel); } catch (Exception exception) { LogException(exception); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } [HttpPost] [ValidateJsonAntiForgeryToken] [AreaSecurity(area = Areas.ActivityCalendar, level = AccessLevel.Read)] public ActionResult GetFilterOptions() { try { string userIdAsText = User.Identity.GetID(); var userId = Guid.Parse(userIdAsText); var acManager = new ActivityCalendarManager(DbContext); var model = acManager.GetActivityCalendarFilterOptions(userId); if (model == null) throw new InvalidOperationException(Messages.Common_OperationWasTerminatedBecauseModelIsNull); return BigJson(model); } catch (Exception exception) { LogException(exception); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } [HttpPost] [ValidateJsonAntiForgeryToken] public ActionResult GetResourceDetailsRights() { try { var model = new { Read = SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceTimeAllocation, AccessLevel.Read), Write = SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceTimeAllocation, AccessLevel.Write), ForecastRead = SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceTimeAllocationProjected, AccessLevel.Read), ForecastWrite = SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceTimeAllocationProjected, AccessLevel.Write), ActualsRead = SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceTimeAllocationActual, AccessLevel.Read), ActualsWrite = SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceTimeAllocationActual, AccessLevel.Write), }; return BigJson(model); } catch (Exception exception) { LogException(exception); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } #endregion #region Private Methods private void DoWorkFlowAction(List actions, string userid) { if (actions != null) { WorkFlowManager wfman = new WorkFlowManager(DbContext); foreach (var wfActions in actions) { if (wfActions.HasChanges) { if (wfActions.ScenarioId.HasValue) { var documentId = wfActions.ScenarioId.Value; var cmd = wfActions.Commands.FirstOrDefault(x => x.Selected); if (cmd != null) { wfman.ExecuteCommand(documentId, cmd.command, Guid.Parse(userid)); } } } } } } #endregion } }