EnVisageOnline/Main-RMO/Source/EnVisage/Models/ProjectModel.cs

625 lines
27 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using EnVisage.Code;
//using Excel;
namespace EnVisage.Models
{
public class ProjectModel : IBaseModel<Project>, IValidatableObject
{
public Guid Id { get; set; }
[Required]
[MaxLength(100, ErrorMessage = "Name should not exceed 100 characters")]
[Display(Name = "Name")]
public string Name { get; set; }
[MaxLength(50, ErrorMessage = "Project Number should not exceed 50 characters")] // SA. ENV-906. Added
[Display(Name = "Project Number")]
public string Number { get; set; }
//[Required]
[Display(Name = "Status")]
public Guid StatusId { get; set; }
[Display(Name = "Status")]
public string StatusName { get; set; }
//[Required]
[Display(Name = "Type")]
public Guid TypeId { get; set; }
[Display(Name = "Type")]
public string TypeName { get; set; }
//[Required]
[Display(Name = "Client")]
public Guid? ClientId { get; set; }
[Display(Name = "Client")]
public string ClientName { get; set; }
[Required]
[Display(Name = "Company")]
public Guid? CompanyId { get; set; }
[Display(Name = "Company")]
public string CompanyName { get; set; }
[MaxLength(8)]
public string Color { get; set; }
[Display(Name = "Details")]
[MaxLength(2000, ErrorMessage = "Details text should not exceed 2000 characters")] // SA. ENV-906. Added message
public string Details { get; set; }
[Display(Name = "Number of Scenarios")]
public int ScenariosCount { get; set; }
[Display(Name = "Priority")]
[Range(0, 25, ErrorMessage = "Your priority must be a whole number from 1 to 25")]
public int Priority { get; set; }
[Display(Name = "Probability")]
[Range(0, 100)]
[UIHint("Slider")]
public short Probability { get; set; }
[Display(Name = "Revenue Generating")]
public bool IsRevenueGenerating { get; set; }
[Display(Name = "Deadline")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yy}", ApplyFormatInEditMode = true)]
public DateTime? Deadline { get; set; }
[Display(Name = "Teams")]
public List<Guid> AssignedTeams { get; set; }
[Display(Name = "Internal Contacts")]
public List<Guid> InternalContacts { get; set; }
[Display(Name = "External Contacts")]
public List<Guid> ExternalContacts { get; set; }
[Display(Name = "Performance Green Threshold")]
[Range(0, 100)]
public short? PerformanceYellowThreshold { get; set; }
[Display(Name = "Performance Red Threshold")]
[Range(0, 100)]
public short? PerformanceRedThreshold { get; set; }
[Display(Name = "Strategic Goals")]
public List<Guid> StrategicGoals { get; set; }
public Guid? ExpandedPartId { get; set; }
public int PartsCount { get; set; }
public bool IsProbability100 { get; set; }
public Guid? ParentProjectId { get; set; }
public bool DeletedPart { get; set; }
[Display(Name = "Project has multiple parts")]
public bool HasChildren { get; set; }
public bool InitialHasChildrenState { get; set; }
public Guid? TemplateId { get; set; }
public bool SaveAsCopy { get; set; }
public bool ContinueToScenarios { get; set; }
public virtual List<ScenarioTabModel> Scenarios { get; set; }
public virtual List<Scenario> InactiveScenarios { get; set; }
public Guid? PartForScenarioId { get; set; }
public List<NoteModel> Notes
{
get
{
var result = new List<NoteModel>();
using (var dbContext = new EnVisageEntities())
{
var notes = (from c in dbContext.Notes where c.ParentId == Id select c).ToList();
result.AddRange(notes.Select(note => (NoteModel) note));
}
return result;
}
}
public IList<ProjectPartModel> Parts { get; set; }
public string BackUrl { get; set; }
public string BackName { get; set; }
public string Timestamp { get; set; }
/// <summary>
/// Casts a <see cref="Project"/> obect to the object of type <see cref="ProjectModel"/>.
/// </summary>
/// <param name="obj">A <see cref="Project"/> object.</param>
/// <returns>A <see cref="ProjectModel"/> object filled with data from db.</returns>
public static explicit operator ProjectModel(Project obj)
{
if (obj == null)
return null;
var model = new ProjectModel
{
Id = obj.Id,
Name = obj.Name,
Number = obj.ProjectNumber,
StatusId = obj.StatusId,
StatusName = obj.Status != null ? obj.Status.Name : string.Empty,
TypeId = obj.TypeId,
TypeName = obj.Type != null ? obj.Type.Name : string.Empty,
ClientId = obj.ClientId,
ClientName = obj.Client != null ? obj.Client.Name : string.Empty,
CompanyId = obj.CompanyId,
CompanyName = obj.Company != null ? obj.Company.Name : string.Empty,
Color = obj.Color,
Details = obj.Details,
ScenariosCount = 0,
Priority = obj.Priority,
IsRevenueGenerating = obj.IsRevenueGenerating,
Deadline = obj.Deadline,
Probability = Convert.ToInt16(obj.Probability * 100),
IsProbability100 = obj.Status != null && obj.Status.Probability100,
Scenarios = new List<ScenarioTabModel>(),
InactiveScenarios = new List<Scenario>(),
Parts = new List<ProjectPartModel>(),
HasChildren = obj.HasChildren,
InitialHasChildrenState = obj.HasChildren,
ParentProjectId = obj.ParentProjectId,
PerformanceYellowThreshold = obj.PerformanceYellowThreshold == null ? (short?)null : Convert.ToInt16(obj.PerformanceYellowThreshold.Value * 100),
PerformanceRedThreshold = obj.PerformanceRedThreshold == null ? (short?)null : Convert.ToInt16(obj.PerformanceRedThreshold.Value * 100),
Timestamp = obj.DateEdited.ByteArrayToString()
};
if (model.HasChildren)
{
foreach (var childProject in obj.ChildProjects.OrderBy(pp=>pp.PartNum))
{
var part = (ProjectPartModel) childProject;
model.Parts.Add(part);
foreach (var scenario in childProject.Scenarios)
{
if (scenario.Type != ScenarioType.Actuals.GetHashCode())
model.ScenariosCount++;
model.Scenarios.Add((ScenarioTabModel)scenario);
}
part.AssignedTeams = childProject.Team2Project.Select(t => t.TeamId).ToList();
part.StrategicGoals = childProject.StrategicGoal2Project.Select(s => s.StrategicGoalId).ToList();
var partContacts = childProject.Contact2Project.Select(c => c.Contact);
part.InternalContacts = partContacts.Where(c => c.Type == ContactType.CompanyContact.GetHashCode()).Select(c => c.Id).ToList();
part.ExternalContacts = partContacts.Where(c => c.Type == ContactType.ClientContact.GetHashCode()).Select(c => c.Id).ToList();
part.CompanyId = model.CompanyId;
part.TrimStringProperties();
}
}
else if (!obj.ParentProjectId.HasValue)
{
// if this is a main project then add one part to display it as main project properties
model.Parts.Add(new ProjectPartModel
{
StatusId = obj.StatusId,
StatusName = obj.Status != null ? obj.Status.Name : string.Empty,
TypeId = obj.TypeId,
TypeName = obj.Type != null ? obj.Type.Name : string.Empty,
ClientId = obj.ClientId,
ClientName = obj.Client != null ? obj.Client.Name : string.Empty,
Details = obj.Details,
Priority = obj.Priority,
IsRevenueGenerating = obj.IsRevenueGenerating,
Deadline = obj.Deadline,
Probability = Convert.ToInt16(obj.Probability * 100),
IsProbability100 = obj.Status != null && obj.Status.Probability100,
ParentProjectId = obj.Id,
AssignedTeams = obj.Team2Project.Select(t2p => t2p.TeamId).ToList(),
StrategicGoals = obj.StrategicGoal2Project.Select(s2p => s2p.StrategicGoalId).ToList(),
CompanyId = obj.CompanyId,
PerformanceYellowThreshold = obj.PerformanceYellowThreshold == null ? (short?)null : Convert.ToInt16(obj.PerformanceYellowThreshold.Value * 100),
PerformanceRedThreshold = obj.PerformanceRedThreshold == null ? (short?)null : Convert.ToInt16(obj.PerformanceRedThreshold.Value * 100),
UseThreshold = obj.PerformanceYellowThreshold != null
});
foreach (var scenario in obj.Scenarios)
{
if (scenario.Type != ScenarioType.Actuals.GetHashCode())
model.ScenariosCount++;
model.Scenarios.Add((ScenarioTabModel)scenario);
}
model.Parts[0].AssignedTeams = obj.Team2Project.Select(t2p => t2p.TeamId).ToList();
model.Parts[0].StrategicGoals = obj.StrategicGoal2Project.Select(s2p => s2p.StrategicGoalId).ToList();
var contacts = obj.Contact2Project.Select(c2p => c2p.Contact);
model.Parts[0].InternalContacts = contacts.Where(c => c.Type == ContactType.CompanyContact.GetHashCode()).Select(c => c.Id).ToList();
model.Parts[0].ExternalContacts = contacts.Where(c => c.Type == ContactType.ClientContact.GetHashCode()).Select(c => c.Id).ToList();
if (model.Parts[0].Attachments == null)
model.Parts[0].Attachments = new List<AttachmentModel>();
}
model.PartsCount = model.Parts.Count;
model.TrimStringProperties();
// SA. ENV-502. Attachments
if (model.PartsCount > 0)
{
IEnumerable<Attachment> allAttachments;
using (var dbContext = new EnVisageEntities())
{
if ((model.PartsCount == 1) && model.Parts.First().Id.Equals(Guid.Empty))
{
// Project has no parts. Single existing in model part is virtual
model.Parts[0].Attachments = dbContext.Attachments
.Where(x => x.ParentId.Equals(model.Id)).ToList().Select(y => (AttachmentModel)y).ToList();
}
else
{
// Project has parts
var partIds = model.Parts.Select(x => x.Id);
allAttachments = dbContext.Attachments.AsNoTracking()
.Where(x => partIds.Contains(x.ParentId));
foreach (ProjectPartModel part in model.Parts)
{
part.Attachments = allAttachments.Where(x => x.ParentId.Equals(part.Id)).ToList()
.Select(y => (AttachmentModel)y).ToList();
}
}
}
}
return model;
}
/// <summary>
/// Copies data from model to DAL object.
/// </summary>
/// <param name="dbObj">A target DAL object.</param>
public void CopyTo(Project dbObj)
{
if (dbObj == null)
throw new ArgumentNullException();
dbObj.Name = Name;
dbObj.ProjectNumber = Number;
dbObj.StatusId = StatusId;
dbObj.TypeId = TypeId;
dbObj.ClientId = ClientId;
dbObj.CompanyId = CompanyId;
dbObj.Details = Details;
dbObj.Color = Color != null ? Color.Replace("#", "") : Color;
dbObj.Priority = Priority;
dbObj.Probability = Probability / 100.0M;
dbObj.IsRevenueGenerating = IsRevenueGenerating;
dbObj.Deadline = Deadline;
dbObj.HasChildren = HasChildren;
dbObj.PerformanceYellowThreshold = PerformanceYellowThreshold == null ? (decimal?)null : PerformanceYellowThreshold.Value / 100.0M;
dbObj.PerformanceRedThreshold = PerformanceRedThreshold == null ? (decimal?)null : PerformanceRedThreshold.Value / 100.0M;
}
public ProjectModel Clone()
{
return new ProjectModel
{
Id = this.Id,
TemplateId = this.TemplateId,
ClientId = this.ClientId,
ClientName = this.ClientName,
Color = this.Color,
CompanyId = this.CompanyId,
CompanyName = this.CompanyName,
Details = this.Details,
InactiveScenarios = this.InactiveScenarios,
IsRevenueGenerating = this.IsRevenueGenerating,
Deadline = this.Deadline,
Name = this.Name,
Number = this.Number,
Priority = this.Priority,
Probability = this.Probability,
SaveAsCopy = this.SaveAsCopy,
ContinueToScenarios = this.ContinueToScenarios,
Scenarios = this.Scenarios,
ScenariosCount = this.ScenariosCount,
StatusId = this.StatusId,
StatusName = this.StatusName,
TypeId = this.TypeId,
TypeName = this.TypeName,
AssignedTeams = this.AssignedTeams,
StrategicGoals = this.StrategicGoals,
InternalContacts = this.InternalContacts,
ExternalContacts = this.ExternalContacts,
DeletedPart = this.DeletedPart,
HasChildren = this.HasChildren,
InitialHasChildrenState = this.HasChildren,
IsProbability100 = this.IsProbability100,
PartsCount = this.PartsCount,
Parts = this.Parts
};
}
public ProjectModel()
{
Parts = new List<ProjectPartModel>();
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (HasChildren && Parts != null && Parts.Count > 0)
{
for (var i = 0; i < Parts.Count;i++)
{
if (string.IsNullOrEmpty(Parts[i].Name))
yield return new ValidationResult(string.Format(Constants.ERROR_TEMPLATE_REQUIRED, "Part " + (i+1) + " Name"), null);
}
}
}
}
public class ProjectPartModel : IBaseModel<Project>, IValidatableObject
{
public Guid Id { get; set; }
//[Required]
[MaxLength(100, ErrorMessage = "Name should not exceed 100 characters")]
[Display(Name = "Name")]
public string Name { get; set; }
[Required]
[Display(Name = "Status")]
public Guid StatusId { get; set; }
[Display(Name = "Status")]
public string StatusName { get; set; }
[Required]
[Display(Name = "Type")]
public Guid TypeId { get; set; }
[Display(Name = "Type")]
public string TypeName { get; set; }
[Required]
[Display(Name = "Client")]
public Guid? ClientId { get; set; }
[Display(Name = "Client")]
public string ClientName { get; set; }
[Display(Name = "Details")]
[MaxLength(2000, ErrorMessage = "Details text should not exceed 2000 characters")] // SA. ENV-906. Added message
public string Details { get; set; }
[Display(Name = "Priority")]
[Range(1, 25, ErrorMessage = "Your priority must be a whole number from 1 to 25")]
public int Priority { get; set; }
[Display(Name = "Probability")]
[Range(0, 100)]
[UIHint("Slider")]
public short Probability { get; set; }
[Display(Name = "Performance Indicators")]
public bool UseThreshold { get; set; }
[Display(Name = "Revenue Generating")]
public bool IsRevenueGenerating { get; set; }
[Display(Name = "Deadline")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yy}", ApplyFormatInEditMode = true)]
public DateTime? Deadline { get; set; }
[Display(Name = "Teams")]
public List<Guid> AssignedTeams { get; set; }
[Display(Name = "Internal Contacts")]
public List<Guid> InternalContacts { get; set; }
[Display(Name = "External Contacts")]
public List<Guid> ExternalContacts { get; set; }
[Display(Name = "Performance Green Threshold")]
[Range(0, 100)]
public short? PerformanceYellowThreshold { get; set; }
[Display(Name = "Performance Red Threshold")]
[Range(0, 100)]
public short? PerformanceRedThreshold { get; set; }
[Display(Name = "Strategic Goals")]
public List<Guid> StrategicGoals { get; set; }
public bool IsProbability100 { get; set; }
public Guid? ParentProjectId { get; set; }
public bool DeletedPart { get; set; }
public bool SaveAsCopy { get; set; }
public Guid? CompanyId { get; set; }
public Guid? OldId { get; set; }
public int? PartNum { get; set; }
[UIHint("FileUploadModel")]
public IList<AttachmentModel> Attachments { get; set; }
/// <summary>
/// Casts a <see cref="Project"/> obect to the object of type <see cref="ProjectPartModel"/>.
/// </summary>
/// <param name="obj">A <see cref="Project"/> object.</param>
/// <returns>A <see cref="ProjectModel"/> object filled with data from db.</returns>
public static explicit operator ProjectPartModel(Project obj)
{
if (obj == null)
return null;
var model = new ProjectPartModel
{
Id = obj.Id,
Name = obj.Name,
StatusId = obj.StatusId,
StatusName = obj.Status != null ? obj.Status.Name : string.Empty,
TypeId = obj.TypeId,
TypeName = obj.Type != null ? obj.Type.Name : string.Empty,
ClientId = obj.ClientId,
ClientName = obj.Client != null ? obj.Client.Name : string.Empty,
Details = obj.Details,
Priority = obj.Priority,
IsRevenueGenerating = obj.IsRevenueGenerating,
Deadline = obj.Deadline,
Probability = Convert.ToInt16(obj.Probability * 100),
IsProbability100 = obj.Status != null && obj.Status.Probability100,
ParentProjectId = obj.ParentProjectId,
PerformanceYellowThreshold = obj.PerformanceYellowThreshold == null ? (short?)null : Convert.ToInt16(obj.PerformanceYellowThreshold.Value * 100),
PerformanceRedThreshold = obj.PerformanceRedThreshold == null ? (short?)null : Convert.ToInt16(obj.PerformanceRedThreshold.Value * 100),
PartNum = obj.PartNum,
UseThreshold = obj.PerformanceYellowThreshold != null
};
model.AssignedTeams = obj.Team2Project.Select(t2p => t2p.TeamId).ToList();
model.StrategicGoals = obj.StrategicGoal2Project.Select(s2p => s2p.StrategicGoalId).ToList();
var contacts = obj.Contact2Project.Select(c2p => c2p.Contact);
model.InternalContacts = contacts.Where(c => c.Type == ContactType.CompanyContact.GetHashCode()).Select(c => c.Id).ToList();
model.ExternalContacts = contacts.Where(c => c.Type == ContactType.ClientContact.GetHashCode()).Select(c => c.Id).ToList();
if (model.Attachments == null)
model.Attachments = new List<AttachmentModel>();
model.TrimStringProperties();
return model;
}
/// <summary>
/// Copies data from model to DAL object.
/// </summary>
/// <param name="dbObj">A target DAL object.</param>
public void CopyTo(Project dbObj)
{
if (dbObj == null)
throw new ArgumentNullException();
dbObj.Name = Name;
dbObj.StatusId = StatusId;
dbObj.TypeId = TypeId;
dbObj.ClientId = ClientId;
dbObj.Details = Details;
dbObj.Priority = Priority;
dbObj.Probability = Probability / 100.0M;
dbObj.IsRevenueGenerating = IsRevenueGenerating;
dbObj.Deadline = Deadline;
dbObj.ParentProjectId = ParentProjectId;
dbObj.PerformanceYellowThreshold = (PerformanceYellowThreshold == null || !UseThreshold) ? (decimal?)null : PerformanceYellowThreshold.Value / 100.0M;
dbObj.PerformanceRedThreshold = (PerformanceRedThreshold == null || !UseThreshold) ? (decimal?)null : PerformanceRedThreshold.Value / 100.0M;
dbObj.Color = null;
dbObj.CompanyId = null;
dbObj.ProjectNumber = null;
dbObj.PartNum = PartNum;
}
public ProjectPartModel Clone()
{
return new ProjectPartModel
{
Id = this.Id,
ClientId = this.ClientId,
ClientName = this.ClientName,
Details = this.Details,
IsRevenueGenerating = this.IsRevenueGenerating,
Deadline = this.Deadline,
Name = this.Name,
Priority = this.Priority,
Probability = this.Probability,
StatusId = this.StatusId,
StatusName = this.StatusName,
TypeId = this.TypeId,
TypeName = this.TypeName,
AssignedTeams = this.AssignedTeams,
StrategicGoals = this.StrategicGoals,
InternalContacts = this.InternalContacts,
ExternalContacts = this.ExternalContacts,
DeletedPart = this.DeletedPart,
IsProbability100 = this.IsProbability100,
OldId = this.Id ,
ParentProjectId = this.ParentProjectId,
PerformanceRedThreshold = this.PerformanceRedThreshold,
PerformanceYellowThreshold = this.PerformanceYellowThreshold,
PartNum = this.PartNum,
Attachments = this.Attachments
};
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (PerformanceYellowThreshold.HasValue && PerformanceRedThreshold.HasValue &&
PerformanceYellowThreshold > PerformanceRedThreshold)
{
yield return
new ValidationResult("Performance Yellow value cannot be greater than Red value",
new[] { "PerformanceYellowThreshold" });
}
if (Deadline.HasValue)
{
var _Id = (Id == Guid.Empty) ? ParentProjectId : Id;
var DbContext = new EnVisageEntities();
var ActiveScenario = DbContext.Scenarios.Where(x => x.ParentId == _Id && x.Status == (int)ScenarioStatus.Active).FirstOrDefault();
var ActualsScenario = DbContext.Scenarios.Where(x => x.ParentId == _Id && x.Type == (int)ScenarioType.Actuals).FirstOrDefault();
if ((ActiveScenario != null && ActiveScenario.EndDate.HasValue && Deadline.Value < ActiveScenario.EndDate.Value) || (ActualsScenario != null && ActualsScenario.EndDate.HasValue && Deadline.Value < ActualsScenario.EndDate.Value))
yield return new ValidationResult(Constants.ERROR_DEADLINE_DATE_LATE, new[] { "Deadline" });
}
}
}
/// <summary>
/// An UI representation of project to be displayed as list items
/// </summary>
public class ProjectListModel
{
public Guid Id { get; set; }
public Guid ProjectId { get; set; }
public string ProjectName { get; set; }
public string ProjectNumber { get; set; }
public string Status { get; set; }
public int Priority { get; set; }
public short Probability { get; set; }
public string Classification { get; set; }
public string Client { get; set; }
public string Company { get; set; }
public string Teams { get; set; }
public string Team { get; set; }
public Guid TeamId { get; set; }
public bool WritePermissionEnabledForCurrentUser { get; set; }
public ScenarioInProjectModel ActiveScenario { get; set; }
public List<ScenarioInProjectModel> InactiveScenarios { get; set; }
public bool HasChildren { get; set; }
public List<ProjectPartListModel> ProjectParts { get; set; }
public int? PartNum { get; set; }
public DateTime? Deadline { get; set; }
public int Rank { get; set; }
}
public class ProjectPartListModel : ProjectListModel
{
}
public class ScenarioInProjectModel : IComparable<ScenarioInProjectModel>
{
public Guid Id { get; set; }
public string Name { get; set; }
public int CompareTo(ScenarioInProjectModel other)
{
if (Name == null && other == null)
return 0;
if (Name == null)
return -1;
if (other == null)
return 1;
return Name.CompareTo(other.Name);
}
}
public class ImportActualsModel
{
public Guid Id { get; set; }
public string ProjectName { get; set; }
public List<ImportActualsProject> Projects { get; set; }
public bool ResetActuals { get; set; }
public Guid SessionId { get; set; }
public bool ImportSuccessful { get; set; }
public string Message { get; set; }
public ImportActualsModel()
{
Projects = new List<ImportActualsProject>();
}
}
public class ImportActualsProject
{
public Guid ProjectId { get; set; }
public string ProjectName { get; set; }
public Guid ActualsScenarioId { get; set; }
public bool Checked { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public List<ImportActualsProjectPart> ProjectParts { get; set; }
public Dictionary<Guid, int> ProjectPartsDistribution { get; set; }
public ImportActualsProject()
{
ProjectParts = new List<ImportActualsProjectPart>();
ProjectPartsDistribution = new Dictionary<Guid, int>();
}
}
public class ImportActualsProjectPart
{
public Guid PartId { get; set; }
public string PartName { get; set; }
public bool Checked { get; set; }
public Guid ActualsScenarioId { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public int Distribution { get; set; }
}
public class ImportActualsScenarioDetails
{
public Guid Id { get; set; }
public Guid? SDId { get; set; }
public Guid ParentId { get; set; }
public Guid ProjectId { get; set; }
public Guid ExpenditureCategoryId { get; set; }
public DateTime WeekEndingDate { get; set; }
public decimal Cost { get; set; }
public decimal Quantity { get; set; }
}
}