EnVisageOnline/Main/Source/EnVisage/Controllers/PeopleResourceController.cs

976 lines
42 KiB
C#

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<Guid>();
newItemModel.Resources = new List<Guid>();
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<Guid>();
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<NonProjectTimeListItemModel> GetNonProjectTimeList(Guid? teamId, Guid? resourceId, bool permanent, bool ishistory, int startIndex,
int pageSize,
IEnumerable<SortedColumn> sortedColumns,
out int totalRecordCount,
out int searchRecordCount,
string searchString)
{
DateTime dt = DateTime.UtcNow.Date;
NonProjectTimeManager mngr = new NonProjectTimeManager(this.DbContext);
List<NonProjectTimeListItemModel> query = new List<NonProjectTimeListItemModel>();
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);
}
/// <summary>
/// Fills ViewBag with lists, that used as select control data options on the edit resource form
/// </summary>
/// <param name="model"></param>
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<DateTime> 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<string, NonProjectTimeDistributionModel>()
{
{ weekDistribution.EndDate.ToString(), weekDistribution }
};
return Json(allocations);
}
}
catch (Exception ex)
{
LogException(ex);
}
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
}
[HttpPost]
[ValidateJsonAntiForgeryToken]
public ActionResult LoadResourcesWithTeams4Resources(List<Guid> model)
{
if (model == null || !model.Any())
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
try
{
var dictionary = new Dictionary<string, PeopleResourceWithTeamsApiModel>();
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<Guid> model)
{
if (model == null || !model.Any())
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
try
{
var dictionary = new Dictionary<string, PeopleResourceWithTeamsApiModel>();
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);
}
}
}