using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using EnVisage.Code; using System.Linq; using EnVisage.Code.BLL; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.EntityFramework; using System.Web.Mvc; namespace EnVisage.Models { public class TeamModel : IBaseModel { public Guid Id { get; set; } [Required] [MaxLength(100, ErrorMessage = "Team name should not exceed 100 characters")] [Display(Name = "Team Name")] public string Name { get; set; } [Required] [Display(Name = "Business Unit")] public Guid? CompanyId { get; set; } [Required] [Display(Name = "Cost Center")] public Guid? CostCenterId { get; set; } [Display(Name = "Report To")] public Guid? ReportToId { get; set; } public Guid? PlannedCapacityScenarioId { get; set; } public Guid? ActualCapacityScenarioId { get; set; } [UIHint("MultipleSelect")] [Display(Name = "Contributors")] public IList UserId { get; set; } [Display(Name = "Inherit Capacity From")] public Guid? CapacityTeamId { get; set; } [Display(Name = "Capacity Type")] public bool CopyPlanned { get; set; } [UIHint("MultipleSelect")] [Display(Name = "Workflow Contacts")] public IList WorkFlowContacts { get; set; } [UIHint("MultipleSelect")] [Display(Name = "Notification List")] public IList NotificationContacts { get; set; } [UIHint("MultipleSelect")] [Display(Name = "Notification Workflow States")] public IList NotificationWorkFlowStates { get; set; } [Display(Name = "Send in-app notification when team is added to a project")] public bool ProjectAddNotification { get; set; } public IEnumerable Users { get { EnVisageEntities DbContext = new EnVisageEntities(); return DbContext.AspNetUsers; } } public static explicit operator TeamModel(MixTeamModel mixTeam) { if (mixTeam == null) return null; var team = new TeamModel() { Name = mixTeam.Name, CompanyId = mixTeam.CompanyId, CostCenterId = mixTeam.CostCenterId, UserId = mixTeam.UserId }; if (!string.IsNullOrWhiteSpace(mixTeam.Id)) { Guid teamId; if (Guid.TryParse(mixTeam.Id, out teamId) && !Guid.Empty.Equals(teamId)) team.Id = teamId; } return team; } /// /// Copies data from model to DAL object. /// /// A target DAL object. public void CopyTo(Team dbObj) { if (dbObj == null) throw new ArgumentNullException(); dbObj.Name = Name; dbObj.CostCenterId = CostCenterId; dbObj.CompanyId = CompanyId; dbObj.ReportsTo = ReportToId; dbObj.PlannedCapacityScenarioId = PlannedCapacityScenarioId; dbObj.ActualCapacityScenarioId = ActualCapacityScenarioId; dbObj.ProjectAddNotification = ProjectAddNotification; } } public class TeamInViewModel : TeamModel { public string CompanyName { get; set; } public string CostCenterName { get; set; } public string ReportToName { get; set; } public List TeamUsers { get; set; } } public class TeamWithResourcesModel : TeamModel { public List PeopleResources { get; set; } /// /// Casts a obect to the object of type . /// /// A object. /// A object filled with data from db. public static explicit operator TeamWithResourcesModel(Team obj) { if (obj == null) return null; var model = new TeamWithResourcesModel { Id = obj.Id, Name = obj.Name, CompanyId = obj.CompanyId, CostCenterId = obj.CostCenterId, ReportToId = obj.ReportsTo, PlannedCapacityScenarioId = obj.PlannedCapacityScenarioId, ActualCapacityScenarioId = obj.ActualCapacityScenarioId }; model.TrimStringProperties(); return model; } public TeamWithResourcesModel() { PeopleResources = new List(); } } /// Aggregated information about specified Team public class TeamSummaryInfoModel { public string Id { get; set; } public Guid? CompanyId { get; set; } public string Name { get; set; } public AccessLevel AccessLevel { get; set; } public Dictionary ExpCategories { get; set; } public TeamSummaryInfoModel() { ExpCategories = new Dictionary(); } } /// Aggregated information about Expenditure Category in the specified Team public class ExpCategorySummaryInfoModel { public enum EC_Scenario { UNKNOWN = 0, ACTUALS = 1, PLANNED = 2, TEAM = 4 } public Guid Id { get; set; } public string Name { get; set; } public decimal UomValue { get; set; } public bool AllowResourceAssignment { get; set; } public EC_Scenario ECScenario { get; set; } /// Key - week ending date in milliseconds, value - capacity public Dictionary PlannedCapacityValues { get; set; } /// Key - week ending date in milliseconds, value - capacity public Dictionary ActualCapacityValues { get; set; } /// /// Represents a weekly dictionary of sum of team allocations for the specified expenditure in the specified team. /// /// Key - week ending date in milliseconds, value - sum of team allocations for all matched active scenarios /// or sum of (Team2Scenario.Allocation * ScenarioDetail.Quantity / 100) if team allocation does not exist. public Dictionary NeedCapacity { get; set; } /// Sum of resource allocations for the specified Expenditure Category in the specified Team. /// Key - week ending date in milliseconds, value - capacity public Dictionary AllocatedCapacity { get; set; } /// Contains all resources related to current EC public Dictionary Resources { get; set; } public ExpCategorySummaryInfoModel() { PlannedCapacityValues = new Dictionary(); ActualCapacityValues = new Dictionary(); NeedCapacity = new Dictionary(); AllocatedCapacity = new Dictionary(); Resources = new Dictionary(); AllowResourceAssignment = true; } } /// An item of the collection. Represents an info about specified resource in the specified expenditure category and team. public class ResourceSummaryInfoModel { public class TeamMembershipModel { public Guid TeamId { get; set; } public long StartDate { get; set; } public long? EndDate { get; set; } } public Guid Id { get; set; } public List Teams { get; set; } /// /// Contains total allocated resource capacity between active scenarios for certain week ending (key in milliseconds). /// public Dictionary AllocatedCapacity { get; set; } /// /// Contains total available resource capacity for certain week ending (key in milliseconds). Gets from EC UoM value. /// public Dictionary TotalCapacity { get; set; } /// /// Contains non-project time allocations for current resource splitted by non-project time categories /// public Dictionary NonProjectTime { get; set; } public ResourceSummaryInfoModel() { AllocatedCapacity = new Dictionary(); TotalCapacity = new Dictionary(); NonProjectTime = new Dictionary(); Teams = new List(); } /// /// Merges TeamInfo provided in the parameter into the value. /// If there are no existing record for the same team but for stacked period, then system, just adds entire into the collection. /// If there are existing record for the same team but for stacked period, then system updates existing record by merging date periods. /// If is null or contains empty TeamId then system do nothing. /// /// An instance of class with info to merge. /// /// IMPORTANT: use this method instead of build-in ICollection.Add method to avoid stacked periods. /// public void MergeTeam(ResourceSummaryInfoModel.TeamMembershipModel team) { if (team == null || Guid.Empty.Equals(team.TeamId)) return; var existingTeams = Teams.Where(t => t.TeamId == team.TeamId); if (!existingTeams.Any()) Teams.Add(team); else { var merged = false; foreach (var existingTeam in existingTeams) { if (Utils.IsDateRangesStacked(Utils.ConvertFromUnixDate(existingTeam.StartDate), Utils.ConvertFromUnixDate(team.StartDate), existingTeam.EndDate.HasValue ? Utils.ConvertFromUnixDate(existingTeam.EndDate.Value) : (DateTime?)null, team.EndDate.HasValue ? Utils.ConvertFromUnixDate(team.EndDate.Value) : (DateTime?)null)) { existingTeam.StartDate = Math.Min(existingTeam.StartDate, team.StartDate); if (!existingTeam.EndDate.HasValue || !team.EndDate.HasValue) existingTeam.EndDate = null; else existingTeam.EndDate = Math.Max(existingTeam.EndDate.Value, team.EndDate.Value); merged = true; break; } } if (!merged) Teams.Add(team); } } } /// /// Represents information about NPT allocations specific for people resource and NPT. /// public class ResourceNptModel { public Guid Id { get; set; } public string Name { get; set; } public Guid CategoryId { get; set; } public bool isTeamWide { get; set; } public bool isReadOnly { get; set; } /// /// Gets or sets an Id of resource's own EC. /// public Guid ExpenditureCategoryId { get; set; } public Dictionary Allocations { get; set; } public Dictionary Costs { get; set; } #region Constructors public ResourceNptModel() { Allocations = new Dictionary(); isReadOnly = false; } #endregion } public class TeamWithPermissionsModel { /// /// Gets or sets a Team.Id value of the team which user has access to. /// public Guid TeamId { get; set; } /// /// Gets or sets a AspNetUser.Id value of the user who has access to the team with Id = . /// public string UserId { get; set; } /// /// Gets or sets a team name. /// public string Name { get; set; } /// /// Gets or sets a value indicating whether user has read access to the team or not. /// public bool Read { get; set; } /// /// Gets or sets a value indicating whether user has write access to the team or not. /// public bool Write { get; set; } /// /// Gets a value indicating level of a user's access to the specified Team. /// public AccessLevel AccessLevel { get { return Write ? AccessLevel.Write : Read ? AccessLevel.Read : AccessLevel.None; } } } }