using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using EnVisage.Code; using EnVisage.Models.ValidationAttributes.NonProjectTime; using System.Linq; namespace EnVisage.Models { public class NonProjectTimeModel : IBaseModel { #region Private Variables private bool _isPercentsMode = true; #endregion public Guid Id { get; set; } [Required] [Display(Name = "Start Date")] [DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yy}", ApplyFormatInEditMode = true)] public DateTime NonProjectTimeStartDate { get; set; } private DateTime? _npTimeStartDateOld = null; public DateTime NonProjectTimeStartDateOld { get { return _npTimeStartDateOld ?? NonProjectTimeStartDate; } set { _npTimeStartDateOld = value; } } [RequiredIf("Permanent", false, ErrorMessage = "The End Date field is required.")] [Display(Name = "End Date")] [DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yy}", ApplyFormatInEditMode = true)] [DateGreaterThanOrEqual("NonProjectTimeStartDate", "End Date must be later or equal to Start Date", ValidateIfEmpty = false)] public DateTime? NonProjectTimeEndDate { get; set; } [Required] [Display(Name = "Name")] public string NonProjectTimeName { get; set; } [Required] [Display(Name = "Allocation Category")] public Guid? NonProjectTimeCategoryId { get; set; } [Required] [StringLength(255)] [Display(Name = "Allocation Category")] public string NonProjectTimeCategoryName { get; set; } [Required] [Display(Name = "Cost")] [DisplayFormat(DataFormatString = "{0:0.00}", ApplyFormatInEditMode = true)] public decimal NonProjectTimeCost { get; set; } [Display(Name = "Duration")] public string NonProjectTimeDuration { get { return Utils.FormatDateRange(NonProjectTimeStartDate, NonProjectTimeEndDate, true); } } [Required] [Display(Name = "Assign To")] public bool IsTeamAssignmentMode { get; set; } #region NPT Resources [Display(Name = "Resources")] public List Resources { get; set; } // SA: To store the Resource selection order in UI form, we must get selected resources list // from client as a comma separated string of GUIDs. // NPT Edit form saves selected resources to ResourcesAsText field of the model. // To make Resources property of the model operable, we should parse ResourcesAsText value // and push GUIDs to Resources property of the model [Display(Name = "Resources")] [RequiredIf("IsTeamAssignmentMode", false, ErrorMessage = "Resources must be specified")] public string ResourcesAsText { get { string result = (this.Resources != null) ? String.Join(",", this.Resources) : String.Empty; return result; } set { if (!String.IsNullOrEmpty(value)) { string[] selectedResources = value.Split(new char[] { ',' }); this.Resources = selectedResources.Select(x => new Guid(x)).ToList(); } else this.Resources = new List(); } } #endregion #region NPT Teams [Display(Name = "Teams")] public List Teams { get; set; } [Display(Name = "Teams")] [RequiredIf("IsTeamAssignmentMode", true, ErrorMessage = "Teams must be specified")] public string TeamsAsText { get { string result = (this.Teams != null) ? String.Join(",", this.Teams) : String.Empty; return result; } set { if (!String.IsNullOrEmpty(value)) { string[] selectedTeams = value.Split(new char[] { ',' }); this.Teams = selectedTeams.Select(x => new Guid(x)).ToList(); } else this.Teams = new List(); } } #endregion [Display(Name = "Details")] [StringLength(500)] public string Details { get; set; } [Display(Name = "Time Allocated")] public bool IsPercentsMode { get { return _isPercentsMode; } set { _isPercentsMode = value; } } [NPTimeEffectiveDate(ErrorMessage = "The Effective Date of Change must be equal to Start Date")] [NPTimeEffectiveDateRequired(ErrorMessage = "The Effective Date of Change field is required.")] [DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yy}", ApplyFormatInEditMode = true)] [Display(Name = "Effective Date of Change")] [DateGreaterThanOrEqual("NonProjectTimeStartDate", "Effective Date of Change must be later or equal to Start Date", ValidateIfEmpty = false)] public DateTime? EffectiveDateOfChange { get; set; } public bool IsHistory { get; set; } public bool Permanent { get; set; } private bool? _permanentOld = null; public bool PermanentOld { get { return _permanentOld ?? Permanent; } set { _permanentOld = value; } } public Guid? TeamId { get; set; } public decimal UOMValue { get; set; } public bool IsCurveConstant { get; set; } public List NonProjectTimeAllocations { get; set; } #region Constructors public NonProjectTimeModel() { NonProjectTimeAllocations = new List(); } #endregion #region Overrides public void CopyTo(NonProjectTime obj) { if (obj == null || !NonProjectTimeCategoryId.HasValue) throw new ArgumentNullException(); obj.StartDate = NonProjectTimeStartDate; obj.EndDate = NonProjectTimeEndDate; obj.Name = NonProjectTimeName; obj.NonProjectTimeCategoryId = NonProjectTimeCategoryId.Value; obj.Cost = NonProjectTimeCost; obj.Details = Details; obj.Permanent = Permanent; obj.IsPercentsMode = IsPercentsMode; obj.IsTeamMode = IsTeamAssignmentMode; } public static explicit operator NonProjectTimeModel(NonProjectTime obj) { if (obj == null) return null; NonProjectTimeModel model = new NonProjectTimeModel() { Id = obj.Id, NonProjectTimeName = obj.Name, NonProjectTimeCategoryId = obj.NonProjectTimeCategoryId, NonProjectTimeCategoryName = obj.NonProjectTimeCategory.Name, NonProjectTimeStartDate = obj.StartDate, NonProjectTimeEndDate = obj.EndDate, NonProjectTimeCost = obj.Cost, Permanent = obj.Permanent, Details = obj.Details, IsPercentsMode = obj.IsPercentsMode, IsTeamAssignmentMode = obj.IsTeamMode, IsHistory = (obj.EndDate.HasValue && obj.EndDate.Value < DateTime.Today) }; if (obj.NonProjectTime2Team != null) { model.Teams = obj.NonProjectTime2Team.Select(x => x.TeamId).ToList(); } if (obj.NonProjectTime2Resource != null) { model.Resources = obj.NonProjectTime2Resource.Select(x => x.PeopleResourceId).ToList(); } return model; } #endregion } public class NonProjectTimeAllocationModel { [Display(Name = "Time Off")] [Range(0, int.MaxValue, ErrorMessage = "The field Time Off must be more than 0.")] public int HoursOff { get; set; } public DateTime WeekStartDate { get; set; } public DateTime WeekEndingDate { get; set; } } public class NonProjectTimeListItemModel { public Guid Id { get; set; } public string Name { get; set; } public string CategoryName { get; set; } public DateTime StartDate { get; set; } public DateTime? EndDate { get; set; } public string Duration { get { return Utils.FormatDateRange(StartDate, EndDate, true); } } public string CostFormatted { get { if (!IsInvalid) return string.Format("{0:C2}", Cost); else return "-"; } } public string DateInterval { get { return StartDate.ToShortDateString() + " - " + (EndDate.HasValue ? EndDate.Value.ToShortDateString() : ""); } } public decimal Cost { get; set; } public string Details { get; set; } public decimal TotalHours { get; set; } public decimal TotalUOMHours { get; set; } public decimal TotalPercents { get; set; } public decimal MinPercents { get; set; } public decimal MaxPercents { get; set; } public bool ApproximatePercents { get; set; } public decimal ActualHours4Today { get; set; } public decimal ActualPercents4Today { get; set; } public bool IsPercentMode { get; set; } public bool Permanent { get; set; } public bool IsFromTeam { get; set; } public bool IsInvalid { get; set; } } public class NonProjectTimeDistributionModel { public long StartDate { get; set; } public long EndDate { get; set; } public int HoursOff { get; set; } public int PercentOff { get; set; } public decimal UOMValue { get; set; } } public class NonProjectTimeRecalculationModel { public long? StartDate { get; set; } public long? EndDate { get; set; } /// /// Gets or sets an array of Team.Id values for teams whose HoursOff/PercentOff system should recalculate. /// public Guid[] TeamIds { get; set; } /// /// Gets or sets an array of Resource.Id values for resources whose HoursOff/PercentOff system should recalculate. /// public Guid[] ResourceIds { get; set; } } public class NonProjectTimeSummaryItem { public Guid NonProjectTimeId { get; set; } public string NonProjectTimeName { get; set; } public Guid PeopleResourceId { get; set; } public Guid ExpenditureCategoryId { get; set; } public Guid NonProjectTimeCategoryId { get; set; } public string NonProjectTimeCategoryName { get; set; } public DateTime WeekEndingDate { get; set; } public int HoursOff { get; set; } public decimal Cost { get; set; } public bool IsFromTeam { get; set; } } public class NonProjectTimeDatesCheckResultModel { public enum ViolationType { NoViolation = 0, NptCompletlyBeforeResourceStartDate = 1, NptCompletlyAfterResourceEndDate = 2, NptPartiallyBeforeResourceStartDate = 3, NptPartiallyAfterResourceEndDate = 4, NptOutBothResourceDates = 5, NotMemberOfAnyTeam = 6, IsInactive = 7 } public class ResourceCheckModel { public Guid Id { get; set; } public string Name { get; set; } public ViolationType ViolationType { get; set; } } public class TeamCheckModel { public Guid Id { get; set; } public string Name { get; set; } public List Resources { get; set; } } public bool HasViolation { get; set; } public List Teams { get; set; } public NonProjectTimeDatesCheckResultModel() { Teams = new List(); } } }