using EnVisage.App_Start; using EnVisage.Code.BLL; using EnVisage.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using EnVisage.Code; using System.Net; using jQuery.DataTables.Mvc; using System.Data.Entity.Infrastructure; using System.Text; using EnVisage.Code.Validation; using System.Threading.Tasks; using Resources; namespace EnVisage.Controllers { public class PeopleResourceController : BaseController { private PeopleResourcesManager _manager = null; public PeopleResourcesManager Manager { get { return _manager ?? (_manager = new PeopleResourcesManager(DbContext)); } } [AreaSecurity(area = Areas.PeopleResourceDetails, level = AccessLevel.Read)] public ActionResult Details(Guid? resourceId) { if (!resourceId.HasValue) { var mngr = new Code.BLL.AccountManager(new EnVisageEntities()); resourceId = mngr.GetCurrentResourceId(User.Identity.GetID()); if (resourceId.HasValue) { return RedirectToAction("Details", "PeopleResource", new { resourceId = resourceId.Value.ToString() }); } return RedirectToAction("AccessDenied", "Home"); } else { if (!SecurityManager.CheckSecurityObjectPermission(Areas.AccessToOtherResources, AccessLevel.Read)) { var mngr = new Code.BLL.AccountManager(new EnVisageEntities()); var myResourceId = mngr.GetCurrentResourceId(User.Identity.GetID()); if ((!Guid.Empty.Equals(resourceId) && !Guid.Empty.Equals(myResourceId) && resourceId != myResourceId) // if this is no my resource || !myResourceId.HasValue // if I don't have any resource assigned ) return RedirectToAction("AccessDenied", "Home"); // then deny access to the specified resource details page } } var model = Manager.LoadPeopleResource(resourceId.Value, DateTime.Today, false, true, true); if (SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceNonProjectTime, AccessLevel.Read)) model.NonProjectTimes = (new NonProjectTimeManager(DbContext)).GetNonProjectTimeList(model.Id, false, false, false); return View(model); } [HttpGet] [AreaSecurity(area = Areas.RD_ResourceNonProjectTime, level = AccessLevel.Write)] public ActionResult LoadNonProjectTime(Guid? Id, Guid? resourceId, Guid? teamId) { string userId = User.Identity.GetID(); var accountManager = new AccountManager(DbContext); ViewBag.CurrentResourceId = accountManager.GetCurrentResourceId(userId); ; if (Id.HasValue) { NonProjectTimeManager nptMngr = new NonProjectTimeManager(this.DbContext); var npTime = nptMngr.GetNonProjectTime(Id.Value, userId); if (npTime == null) return HttpNotFound(); npTime.TeamId = teamId.HasValue ? teamId.Value : (Guid?)null; return PartialView("_scheduleNonProjectTime", npTime); } else { Guid? _resId = null; DateTime dt = DateTime.UtcNow; TeamManager tmMngr = new TeamManager(this.DbContext); bool openInTeamMode = !resourceId.HasValue && teamId.HasValue && !teamId.Equals(Guid.Empty); if (openInTeamMode) { // If team only specified, we get first resource from the team // to get it's UOM var teamResources = Manager.LoadPeopleResourcesByTeamNonStrict(teamId.Value, false, dt); _resId = teamResources.Select(x => x.Id).FirstOrDefault(); } if (resourceId.HasValue && !resourceId.Equals(Guid.Empty) && !teamId.HasValue) { // If resource only specified, we get it's team on current Date point var resourceTeams = Manager.GetResourceTeams(resourceId.Value, dt); teamId = resourceTeams.FirstOrDefault(); } #region Load Unit of Measure Value decimal resourceUOM; Guid? resourceToGetUom = (resourceId.HasValue) ? resourceId.Value : _resId.Value; if (resourceToGetUom.HasValue && !resourceToGetUom.Value.Equals(Guid.Empty)) resourceUOM = Manager.GetResourceUOM(resourceToGetUom.Value); else resourceUOM = Manager.GetDafaultUOM(); if (resourceUOM == 0) throw new UOMNotExistsException(); #endregion var newItemModel = new NonProjectTimeModel() { NonProjectTimeStartDate = DateTime.UtcNow.Date, NonProjectTimeEndDate = DateTime.UtcNow.Date.AddDays(14), NonProjectTimeCost = 0, TeamId = teamId.HasValue ? teamId.Value : (Guid?)null, IsTeamAssignmentMode = openInTeamMode }; newItemModel.Teams = new List(); newItemModel.Resources = new List(); if (teamId.HasValue) newItemModel.Teams.Add(teamId.Value); if (resourceId.HasValue) newItemModel.Resources.Add(resourceId.Value); return PartialView("_scheduleNonProjectTime", newItemModel); } } [HttpPost] [ValidateAntiForgeryToken] [AreaSecurity(area = Areas.RD_ResourceNonProjectTime, level = AccessLevel.Write)] public ActionResult DeleteNonProjectTime(Guid deleteNPTimeId, Guid id) { if (ContentLocker.IsLock("NonProjectTime", deleteNPTimeId.ToString(), User.Identity.GetUserName())) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); try { Guid? resourceId; var manager = new NonProjectTimeManager(DbContext); if (!SecurityManager.CheckSecurityObjectPermission(Areas.AccessToOtherResources, AccessLevel.Write)) { resourceId = id; } else resourceId = null; manager.DeleteNPT(deleteNPTimeId, resourceId); this.DbContext.SaveChanges(); return new HttpStatusCodeResult(HttpStatusCode.OK); } catch (Exception ex) { LogException(ex); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } [HttpPost] [ValidateAjax] [ValidateAntiForgeryToken] [AreaSecurity(area = Areas.RD_ResourceNonProjectTime, level = AccessLevel.Write)] public ActionResult ScheduleNonProjectTime(NonProjectTimeModel model) { #if DEBUG var watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); Logger.Debug("Start ScheduleNonProjectTime"); #endif if (model != null && model.Id != Guid.Empty && ContentLocker.IsLock("NonProjectTime", model.Id.ToString(), User.Identity.GetUserName())) { ModelState.AddModelError(string.Empty, Messages.NonProjectTime_Schedule_Another_User); return new FailedJsonResult(ModelState); } try { if (model == null) throw new ArgumentNullException(nameof(model)); model.TrimStringProperties(); var itemsForValidation = new List(); var manager = new NonProjectTimeManager(DbContext); if (!model.IsTeamAssignmentMode && (model.Resources != null) && (model.Resources.Count > 0)) { // Resources to validate dates by NPT-dates itemsForValidation.AddRange(model.Resources); } if (model.IsTeamAssignmentMode && (model.Teams != null) && (model.Teams.Count > 0)) { // Teams to validate resources dates by NPT-dates itemsForValidation.AddRange(model.Teams); } if (!SecurityManager.CheckSecurityObjectPermission(Areas.AccessToOtherResources, AccessLevel.Write)) { var userId = User.Identity.GetID(); var accountManager = new AccountManager(DbContext); var myResourceId = accountManager.GetCurrentResourceId(userId); if (!myResourceId.HasValue) { //TODO: It's necessary to test this case. Handle this case correctly throw new InvalidOperationException("There is no resource associated with current user"); } #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"ScheduleNonProjectTime Validation has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"ScheduleNonProjectTime Validation {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif if ((model.Resources != null) && model.Resources.Any(x => x != myResourceId) && model.Resources.Any(x => x == myResourceId)) { var originalNPT = manager.GetNonProjectTime(model.Id, userId); #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"ScheduleNonProjectTime manager.GetNonProjectTime has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"ScheduleNonProjectTime manager.GetNonProjectTime {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif originalNPT.Resources.Remove(myResourceId.Value); #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"ScheduleNonProjectTime manager.Save has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"ScheduleNonProjectTime manager.Save {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif manager.Save(originalNPT); #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"ScheduleNonProjectTime DbContext.SaveChanges has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"ScheduleNonProjectTime DbContext.SaveChanges {watch1.ElapsedMilliseconds} ms"); watch1 = new System.Diagnostics.Stopwatch(); watch1.Start(); #endif DbContext.BulkSaveChanges(); model.Resources.RemoveAll(x => x != myResourceId); //remove other resources model.Id = Guid.Empty; //to create a new instance } } manager.Save(model); DbContext.BulkSaveChanges(); ContentLocker.RemoveLock("NonProjectTime", model.Id.ToString(), User.Identity.GetUserName()); var result = new NonProjectTimeDatesCheckResultModel(); if (itemsForValidation.Count > 0) { if (!model.IsTeamAssignmentMode) { // Check resources to fit NPT dates result = manager.CheckDateRangeViolationByResources(itemsForValidation, model.NonProjectTimeStartDate, model.NonProjectTimeEndDate); } else { // Check resources in teams to fit NPT dates result = manager.CheckDateRangeViolationByTeams(itemsForValidation, model.NonProjectTimeStartDate, model.NonProjectTimeEndDate); } } #if DEBUG watch1.Stop(); System.Diagnostics.Debug.WriteLine($"ScheduleNonProjectTime End has taken {watch1.ElapsedMilliseconds} ms"); Logger.Debug($"ScheduleNonProjectTime End {watch1.ElapsedMilliseconds} ms"); #endif return new SuccessContentJsonResult(result); } 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); ModelState.AddModelError(string.Empty, Messages.NonProjectTime_Schedule_Cannot_Save); } } catch (Exception exception) // handle any unexpected error { LogException(exception); ModelState.AddModelError(string.Empty, Messages.NonProjectTime_Schedule_Cannot_Save); } return new FailedJsonResult(ModelState); } [HttpGet] [AreaSecurity(area = Areas.RD_ResourceNonProjectTime, level = AccessLevel.Read)] public ActionResult NonProjectTime(Guid? teamId) { if (!teamId.HasValue) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var model = new PeopleResourceModel(); var tm = new TeamManager(DbContext); model.Team = tm.Load(teamId.Value); return View(model); } [HttpPost] [AreaSecurity(area = Areas.RD_ResourceNonProjectTime, level = AccessLevel.Read)] public JsonResult LoadNonProjectTimeList(JQueryDataTablesModel jQueryDataTablesModel, Guid? teamId, Guid? resourceId, bool permanent, bool ishistory) { int totalRecordCount; int searchRecordCount; var npTimes = GetNonProjectTimeList(teamId, resourceId, permanent, ishistory, startIndex: jQueryDataTablesModel.iDisplayStart, pageSize: jQueryDataTablesModel.iDisplayLength, sortedColumns: jQueryDataTablesModel.GetSortedColumns(), totalRecordCount: out totalRecordCount, searchRecordCount: out searchRecordCount, searchString: jQueryDataTablesModel.sSearch); return this.DataTablesJson(items: npTimes, totalRecords: totalRecordCount, totalDisplayRecords: searchRecordCount, sEcho: jQueryDataTablesModel.sEcho); } public IEnumerable GetNonProjectTimeList(Guid? teamId, Guid? resourceId, bool permanent, bool ishistory, int startIndex, int pageSize, IEnumerable sortedColumns, out int totalRecordCount, out int searchRecordCount, string searchString) { DateTime dt = DateTime.UtcNow.Date; NonProjectTimeManager mngr = new NonProjectTimeManager(this.DbContext); List query = new List(); if (teamId.HasValue) query = mngr.GetNonProjectTimes4Team(teamId.Value, permanent, ishistory, dt); if (resourceId.HasValue) query = mngr.GetNonProjectTimeList(resourceId.Value, permanent, ishistory, (!permanent)); // Perform ordering if (ishistory) query = query.OrderByDescending(x => x.StartDate).ThenBy(x => x.EndDate).ThenBy(x => x.Name).ToList(); else { if (!permanent) query = query.OrderBy(x => x.StartDate).ThenByDescending(x => x.EndDate).ThenBy(x => x.Name).ToList(); else query = query.OrderBy(x => x.StartDate).ThenByDescending(x => x.Name).ToList(); } totalRecordCount = query.Count(); searchRecordCount = query.Count(); return query.Skip(startIndex).Take(pageSize).ToList(); } [HttpPost] [AreaSecurity(area = Areas.Resources, level = AccessLevel.Write)] public ActionResult Details(PeopleResourceModel model) { model.TrimStringProperties(); if (ModelState.IsValid) { try { Manager.Save(model); DbContext.SaveChanges(); return RedirectToAction("Index"); } catch (BLLException blEx) { if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } } catch (Exception exception) { LogException(exception); SetErrorScript(); } } return View(model); } protected void WriteExpendituresListToViewBag(Guid? selectedExpCatId) { ViewBag.ExpendituresList = Utils.GetResourceExpendituresList(selectedExpCatId.HasValue && !selectedExpCatId.Value.Equals(Guid.Empty) ? selectedExpCatId.Value : Guid.Empty, false); } /// /// Fills ViewBag with lists, that used as select control data options on the edit resource form /// /// protected void InitViewBagLists(PeopleResourceModel model) { ViewBag.TeamsList = Utils.GetTeamsAvailableForUser(Guid.Parse(User.Identity.GetID()), selectedTeam: model.TeamId); ViewBag.WorkWeeks = Utils.GetResourceWorkWeeksList(model.WorkWeekId); WriteExpendituresListToViewBag(model.ExpenditureCategoryId); ViewBag.MaxDate = Constants.FISCAL_CALENDAR_MAX_DATE.ToShortDateString(); List weekendings = FiscalCalendarManager.GetWeekendingsByRange(DateTime.Today.AddDays(-1), Constants.FISCAL_CALENDAR_MAX_DATE, this.DbContext); ViewBag.WeekendingsNextDays = weekendings.ToDictionary(k => Utils.ConvertToUnixDate(k), v => v.AddDays(1).ToShortDateString()); } [AreaSecurity(area = Areas.RD_ResourceInformation, level = AccessLevel.Write)] public ActionResult Edit(Guid? resourceId, Guid? teamId, Guid? categoryId, bool? noAdjust, long? start, long? end) { var model = new PeopleResourceModel(); model.IsNew = !resourceId.HasValue || resourceId.Value.Equals(Guid.Empty); if (resourceId.HasValue && (resourceId != Guid.Empty)) model = Manager.LoadPeopleResource(resourceId.Value, DateTime.Today, false, true, false); else { if (teamId.HasValue && teamId.Value != Guid.Empty) model.TeamId = teamId.Value; if (categoryId.HasValue && categoryId.Value != Guid.Empty) model.ExpenditureCategoryId = categoryId.Value; if (noAdjust.HasValue && noAdjust.Value == true) model.ChangeCapacity = false; else model.ChangeCapacity = true; var workWeek = DbContext.WorkWeeks.FirstOrDefault(x => x.IsDefault); if (workWeek != null) model.WorkWeekId = workWeek.Id; // If incoming Start Date set (parameter not null), we use parameters to set as resource initial dates. // For creating resource with no incoming date parameters, we set End Date as Start Date + 1 year DateTime utcToday = DateTime.UtcNow.Date; model.StartDate = start.HasValue && start.Value > 0 ? Utils.ConvertFromUnixDate(start.Value).Date : utcToday; model.EffectiveChangeDate = model.StartDate > utcToday ? model.StartDate : utcToday; if (end.HasValue && end.Value > 0) model.EndDate = model.StartDate < Utils.ConvertFromUnixDate(end.Value) ? Utils.ConvertFromUnixDate(end.Value) : model.StartDate.AddYears(1).Date; else model.EndDate = (start.HasValue && start.Value > 0) ? (DateTime?)null : model.StartDate.AddYears(1).Date; model.PermanentResource = !model.EndDate.HasValue || model.EndDate.Value == Constants.FISCAL_CALENDAR_MAX_DATE; } InitViewBagLists(model); return PartialView("_edit", model); } [HttpPost] [AreaSecurity(area = Areas.RD_ResourceInformation, level = AccessLevel.Write)] public ActionResult Edit(PeopleResourceModel model) { if (model == null || (!model.IsNew && ContentLocker.IsLock("PeopleResource", model.Id.ToString(), User.Identity.GetUserName()))) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); model.TrimStringProperties(); var sb = new StringBuilder(); sb.AppendLine("PeopleResourceController.Edit method. model:"); model.DebugObjectProperties(sb); Logger.Debug(sb); if (!ModelState.IsValid) { InitViewBagLists(model); return PartialView("_edit", model); } using (var transaction = DbContext.Database.BeginTransaction()) { var transactionId = DbContext.GetClientConnectionId(); var userId = User.Identity.GetID(); try { PeopleResourceModel oldModel = null; if (!model.IsNew) { oldModel = Manager.LoadPeopleResource(model.Id, DateTime.UtcNow.Date, false, false, true); // When select2 for ExpenditureCastegoryId field was disabled for editing in the form, // form submit sets to model.ExpenditureCategoryId Guid.Empty value, though the field // ExpenditureCategoryId was not changed bu user. We need to restore the old value in this // field to prevent the attempts to change ExpCat for PeopleResource in the code below if (model.ExpenditureCategoryId.Equals(Guid.Empty)) model.ExpenditureCategoryId = oldModel.ExpenditureCategoryId; // Perform resource reassignment if (Manager.ReassignResource(model, oldModel)) DbContext.ExecuteBulkSaveChanges(); } // Perform Resource properties saving Manager.Save(model); DbContext.ExecuteBulkSaveChanges(); transaction.Commit(); Task.Run(() => AuditProxy.CommitHistoryChanges(transactionId, userId)); if (!model.IsNew) ContentLocker.RemoveLock("PeopleResource", model.Id.ToString(), User.Identity.GetUserName()); } catch (BLLException blEx) { transaction.Rollback(); AuditProxy.ClearHistoryChanges(transactionId); if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } } catch (Exception exception) { transaction.Rollback(); AuditProxy.ClearHistoryChanges(transactionId); LogException(exception); SetErrorScript(); } } if (model.AddMore) { //TODO: return _edit partial view with a new model to create another one people ("Edit" action with empty resource id). And do not reload ajax form on client } //InitViewBagLists(model); //return View(model); return Json(model); } [AreaSecurity(area = Areas.RD_ResourceInformation, level = AccessLevel.Write)] public ActionResult ChangeResourceExpenditure(Guid resourceId) { if ((resourceId == null) || resourceId.Equals(Guid.Empty)) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); try { var resourceModel = Manager.LoadPeopleResource(resourceId, DateTime.Today, false, true, true); if (resourceModel != null) { resourceModel.ChangeCapacity = true; var model = new PeopleResourceExpenditureChangeModel(resourceModel); WriteExpendituresListToViewBag(resourceModel.ExpenditureCategoryId); if (resourceModel.ExpenditureCategory != null) model.CurrentExpenditureCategoryName = resourceModel.ExpenditureCategory.GetView().ExpCategoryWithCcName; return PartialView("_changeResourceExpCat", model); } else { return new HttpStatusCodeResult(HttpStatusCode.NotFound); } } catch (Exception ex) { LogException(ex); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } [HttpPost] [AreaSecurity(area = Areas.RD_ResourceInformation, level = AccessLevel.Write)] public ActionResult ChangeResourceExpenditure(PeopleResourceExpenditureChangeModel model) { if (model == null || (model.ResourceId == null) || model.ResourceId.Equals(Guid.Empty) || ContentLocker.IsLock("PeopleResource", model.ResourceId.ToString(), User.Identity.GetUserName())) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); model.TrimStringProperties(); var sb = new StringBuilder(); sb.AppendLine("PeopleResourceController.ChangeResourceExpenditure method. model:"); model.DebugObjectProperties(sb); Logger.Debug(sb); if (ModelState.IsValid && ((model.ExpenditureCategoryId == null) || model.ExpenditureCategoryId.Equals(Guid.Empty))) { ModelState.AddModelError("ExpenditureCategoryId", "New Expenditure Category value can't be empty"); } if (!ModelState.IsValid) { // Save available to select EC list to ViewBag and current resource's EC name WriteExpendituresListToViewBag(model.ExpenditureCategoryId); ContentLocker.RemoveLock("PeopleResource", model.ResourceId.ToString(), User.Identity.GetUserName()); return PartialView("_changeResourceExpCat", model); } using (var transaction = DbContext.Database.BeginTransaction()) { var transactionId = DbContext.GetClientConnectionId(); var userId = User.Identity.GetID(); try { // Perform Resource EC changes Manager.ChangeResourceExpenditureCategory(model.ResourceId, model.ExpenditureCategoryId, model.ChangePlannedCapacity); // it is more efficient way to save data in this place DbContext.SaveChanges(); transaction.Commit(); Task.Run(() => AuditProxy.CommitHistoryChanges(transactionId, userId)); ContentLocker.RemoveLock("PeopleResource", model.ResourceId.ToString(), User.Identity.GetUserName()); } catch (BLLException blEx) { transaction.Rollback(); AuditProxy.ClearHistoryChanges(transactionId); LogException(blEx); return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } catch (Exception exception) { transaction.Rollback(); AuditProxy.ClearHistoryChanges(transactionId); LogException(exception); return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } } return new HttpStatusCodeResult(HttpStatusCode.OK); } [HttpPost] public JsonResult IsUnique(string emailAddress, Guid id) { if (string.IsNullOrWhiteSpace(emailAddress)) return Json(false); try { var isUnique = !PeopleResourcesManager.ResourceByEmailExists(emailAddress, id); return Json(isUnique); } catch (Exception exception) { LogException(exception); return Json(false); } } [HttpPost] [AreaSecurity(area = Areas.RD_ResourceInformation, level = AccessLevel.Write)] public ActionResult DisplayResourceReassignForm(Guid id, long date, Guid? newTeamId) { // Transform incoming date to DateTime var effectiveDateOfChange = Utils.ConvertFromUnixDate(date); var currentUserId = Guid.Parse(User.Identity.GetID()); var model = new PeopleResourceReassignModel() { EffectiveChangeDate = FiscalCalendarManager.GetDateForTeamMembershipStart(effectiveDateOfChange, DbContext), AllocationsReassignmentPlan = Manager.GetResourceSubstitutions(id, effectiveDateOfChange, currentUserId) }; if ((model.AllocationsReassignmentPlan != null) && (model.AllocationsReassignmentPlan.Count > 0)) { if (newTeamId.HasValue) { // Mark projects, which already have New Resource Team model.AllocationsReassignmentPlan.ForEach(p => p.ProjectHasDestTeam = (p.SubstitutionOptions != null) && (p.SubstitutionOptions.Where(t => t.TeamId.Equals(newTeamId.Value)).Count() > 0)); } else { // Resource doesn't have any new team. Any project for reassignment doesn't has dest. team model.AllocationsReassignmentPlan.ForEach(p => p.ProjectHasDestTeam = false); } return PartialView("_reassignResource", model); } // No project to perform reassignment on return new EmptyResult(); } [AreaSecurity(area = Areas.Resources, level = AccessLevel.Write)] public ActionResult Delete(Guid? resourceId) { if (resourceId.HasValue) { var model = Manager.LoadPeopleResourceAsIs(resourceId.Value, DateTime.Today); if (model != null) { model.ChangeCapacity = true; return View(model); } else return new HttpStatusCodeResult(HttpStatusCode.NotFound); } else return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } [HttpPost] [AreaSecurity(area = Areas.Resources, level = AccessLevel.Write)] // TODO: create model class for current specific case using only required properties instead of PeopleResourceModel public ActionResult Delete(PeopleResourceModel model, Guid? teamId) { if (ContentLocker.IsLock("PeopleResource", model.Id.ToString(), User.Identity.GetUserName())) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); var sb = new StringBuilder(); sb.AppendLine("PeopleResourceController.Delete method. model:"); model.DebugObjectProperties(sb); Logger.Debug(sb); using (var transaction = DbContext.Database.BeginTransaction()) { var transactionId = DbContext.GetClientConnectionId(); var userId = User.Identity.GetID(); try { var resource = Manager.LoadPeopleResourceAsIs(model.Id, DateTime.Today); if (resource != null) { resource.ChangeCapacity = model.ChangeCapacity; Manager.DeleteResource(resource); DbContext.ExecuteBulkSaveChanges(); transaction.Commit(); Task.Run(() => AuditProxy.CommitHistoryChanges(transactionId, userId)); ContentLocker.RemoveLock("PeopleResource", resource.Id.ToString(), User.Identity.GetUserName()); return RedirectToAction("Board", "Team", new { @teamId = teamId.Value }); } else throw new Exception(String.Format("Resource (Id='{0}') not found", model.Id.ToString())); } catch (BLLException blEx) { transaction.Rollback(); AuditProxy.ClearHistoryChanges(transactionId); if (blEx.DisplayError) SetErrorScript(message: blEx.Message); else { LogException(blEx); SetErrorScript(); } } catch (Exception exception) { transaction.Rollback(); AuditProxy.ClearHistoryChanges(transactionId); LogException(exception); SetErrorScript(); } } return View(model); } [HttpGet] public ActionResult PeopleResourceFNameSearch(string term) { using (var dbContext = new EnVisageEntities()) { var fnames = (from pr in dbContext.PeopleResources.AsNoTracking() join p2t in dbContext.PeopleResource2Team.AsNoTracking() on pr.Id equals p2t.PeopleResourceId into gr from rel in gr.DefaultIfEmpty() where pr.FirstName.StartsWith(term) && pr.IsActiveEmployee == true && rel == null select pr.FirstName + "," + pr.LastName).Distinct().ToList(); return this.Json(fnames, JsonRequestBehavior.AllowGet); } } [HttpGet] public JsonResult PeopleResourceFullRecord(string name) { char[] splprm = { ',' }; string[] parts = name.Split(splprm); string firstname = parts[0]; string lastname = parts[1]; using (var dbContext = new EnVisageEntities()) { var prRecord = dbContext.PeopleResources.AsNoTracking().Where(x => x.FirstName == firstname && x.LastName == lastname).OrderBy(p => p.FirstName).OrderBy(n => n.LastName); PeopleResource pr = prRecord.Select(x => x).FirstOrDefault(); var pm = new { Id = pr.Id, IsActiveEmployee = pr.IsActiveEmployee, FirstName = pr.FirstName, LastName = pr.LastName, ExpenditureCategoryId = pr.ExpenditureCategoryId, StartDate = String.Format("{0:M/d/yyyy}", pr.StartDate), EndDate = String.Format("{0:M/d/yyyy}", pr.EndDate), EmailAddress = pr.Email, EmployeeID = pr.EmployeeID }; JsonResult rs = this.Json(pm, JsonRequestBehavior.AllowGet); return rs; } } [HttpPost] [AreaSecurity(area = Areas.RD_ResourceNonProjectTime, level = AccessLevel.Write)] public ActionResult RecalculateNPTimeAllocations(NonProjectTimeRecalculationModel model) { if (model == null || !model.StartDate.HasValue) return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); try { var fcManager = (new FiscalCalendarManager(DbContext)); var nptManager = (new NonProjectTimeManager(DbContext)); var firstWeek = fcManager.GetFirstWeek(); if (firstWeek == null) throw new InvalidOperationException("Cannot get the first week of fiscal calendar. Seems like it does not exist."); var lastWeek = fcManager.GetLastWeek(); if (lastWeek == null) throw new InvalidOperationException("Cannot get the last week of fiscal calendar. Seems like it does not exist."); // if user has selected period after fiscal calendar ends var rangeStartDate = Utils.ConvertFromUnixDate(model.StartDate.Value); if (lastWeek.EndDate < rangeStartDate) return null; if (model.EndDate.HasValue) { // if user has selected period befor fiscal calendar starts var rangeEndDate = Utils.ConvertFromUnixDate(model.EndDate.Value); if (rangeEndDate < firstWeek.StartDate) return null; var week = fcManager.GetFirstWeek(rangeEndDate); // if selected end date after fiscal calendar ends we should take the last calendar week var weeks = fcManager.GetFiscalCalendar(FiscalCalendarModel.FiscalYearType.Week, rangeStartDate, (week ?? lastWeek).EndDate, true, null, false); var allocations = nptManager.RecalculateNPTimeAllocations(rangeStartDate, rangeEndDate, weeks, model.ResourceIds, model.TeamIds); return Json(allocations); } else { var weeks = fcManager.GetFiscalCalendar(FiscalCalendarModel.FiscalYearType.Week, rangeStartDate, rangeStartDate, true, null, true); var allocations = nptManager.RecalculateNPTimeAllocations(rangeStartDate, rangeStartDate, weeks, model.ResourceIds, model.TeamIds); var weekending = weeks.Count > 1 ? lastWeek.EndDate : weeks.First().EndDate; var uomValue = 0; if (allocations != null && allocations.Count == 1) { foreach (var item in allocations.Values) { uomValue = Convert.ToInt32(item.UOMValue); break; } } // we should show only one slider/input for permanent non-project time with distribution of 100% var weekDistribution = new NonProjectTimeDistributionModel() { StartDate = model.StartDate.Value, EndDate = Utils.ConvertToUnixDate(weekending), // Utils.ConvertToUnixDate(lastWeek.EndDate), HoursOff = uomValue, UOMValue = uomValue, PercentOff = 100 }; allocations = new Dictionary() { { weekDistribution.EndDate.ToString(), weekDistribution } }; return Json(allocations); } } catch (Exception ex) { LogException(ex); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } [HttpPost] [ValidateJsonAntiForgeryToken] public ActionResult LoadResourcesWithTeams4Resources(List model) { if (model == null || !model.Any()) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); try { var dictionary = new Dictionary(); var resources = (new PeopleResourcesManager(DbContext)).GetPeopleResourceWithTeams4Resources(model); if (resources != null && resources.Any()) { dictionary = resources.Select(x => new PeopleResourceWithTeamsApiModel(x)) .ToDictionary(x => x.Id.ToString()); } return Json(dictionary); } catch (Exception exception) { LogException(exception); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } [HttpPost] [ValidateJsonAntiForgeryToken] public ActionResult LoadResourcesWithTeams4Teams(List model) { if (model == null || !model.Any()) return new HttpStatusCodeResult(HttpStatusCode.BadRequest); try { var dictionary = new Dictionary(); var resources = (new PeopleResourcesManager(DbContext)).GetPeopleResourceWithTeams4Teams(model); if (resources != null && resources.Any()) { dictionary = resources.Select(x => new PeopleResourceWithTeamsApiModel(x)) .ToDictionary(x => x.Id.ToString()); } return Json(dictionary); } catch (Exception exception) { LogException(exception); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } } }