831 lines
38 KiB
C#
831 lines
38 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 EnVisage.Code.BLL;
|
|
//using Excel;
|
|
|
|
namespace EnVisage.Models
|
|
{
|
|
public class ProjectTeamUsage
|
|
{
|
|
public bool HasProjectionsResourceAllocations { get; set; }
|
|
public bool HasActualsResourceAllocations { get; set; }
|
|
}
|
|
|
|
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 = "Business Unit")]
|
|
public Guid? CompanyId { get; set; }
|
|
[Display(Name = "Business Unit")]
|
|
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")]
|
|
public string Details { get; set; }
|
|
[Display(Name = "Number of Scenarios")]
|
|
public int ScenariosCount { get; set; }
|
|
public decimal 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; }
|
|
public Dictionary<Guid, ProjectTeamUsage> TeamsUsage { 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; }
|
|
/// <summary>
|
|
/// Gets a value indicating whether to display Project Dates readonly fields or not
|
|
/// </summary>
|
|
public bool ShowProjectDates
|
|
{
|
|
get
|
|
{
|
|
var dt = DateTime.Today;
|
|
return !string.IsNullOrWhiteSpace(ProjectMinStartDate) && !string.IsNullOrWhiteSpace(ProjectMaxEndDate) &&
|
|
DateTime.TryParse(ProjectMinStartDate, out dt) && DateTime.TryParse(ProjectMaxEndDate, out dt);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets or sets a minimum start date of protfolio scenarios related to any of project parts.
|
|
/// </summary>
|
|
public string ProjectMinStartDate { get; set; }
|
|
/// <summary>
|
|
/// Gets or sets a maximum end date of protfolio scenarios related to any of project parts.
|
|
/// </summary>
|
|
public string ProjectMaxEndDate { 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; }
|
|
[Display(Name = "Portfolio/Product Tag")]
|
|
public List<Guid> PortfolioTags { get; set; }
|
|
[Display(Name = "Project Tag")]
|
|
public List<Guid> ProjectTags { get; set; }
|
|
public List<UDFValueCollection> UserDefinedFields { get; set; }
|
|
[Display(Name = "Workflow Contacts")]
|
|
public List<Guid> WorkFlowContacts { 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;
|
|
// TODO: possible reason of locked objects
|
|
return GetProjectModel(obj, new EnVisageEntities());
|
|
}
|
|
public static ProjectModel GetProjectModel(Project obj, EnVisageEntities dbContext)
|
|
{
|
|
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.EditTimestamp.ByteArrayToString()
|
|
};
|
|
var wfManager = new WorkFlowManager(dbContext);
|
|
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);
|
|
//if (scenario.Status == (int) ScenarioStatus.Active)
|
|
//{
|
|
var wfstate = wfManager.GetCurrentState(scenario.Id);
|
|
if (wfstate != null)
|
|
part.WorkFlowState = wfstate.state;
|
|
//}
|
|
}
|
|
|
|
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).Select(c => c.Id).ToList();
|
|
part.ExternalContacts = partContacts.Where(c => c.Type == ContactType.ClientContact).Select(c => c.Id).ToList();
|
|
part.CompanyId = model.CompanyId;
|
|
part.TrimStringProperties();
|
|
if (part.WorkFlowState == null)
|
|
{
|
|
var scenario = dbContext.Scenarios.FirstOrDefault(x => x.ParentId == part.Id && x.Type == (int)ScenarioType.Portfolio);
|
|
if (scenario != null)
|
|
{
|
|
var wfstate = wfManager.GetCurrentState(scenario.Id);
|
|
if (wfstate != null)
|
|
part.WorkFlowState = wfstate.state;
|
|
}
|
|
else
|
|
{
|
|
var wfstate2 = wfManager.GetCurrentState(part.Id);
|
|
if (wfstate2 != null)
|
|
part.WorkFlowState = wfstate2.state;
|
|
}
|
|
}
|
|
part.ProjectTags = dbContext.TagLinks.Where(x => x.ParentID == part.Id && x.TagLinkType == (int)TagType.Project).OrderBy(x => x.Tag.TagName).Select(x => x.TagID).ToList();
|
|
part.PortfolioTags = dbContext.TagLinks.Where(x => x.ParentID == part.Id && x.TagLinkType == (int)TagType.Portfolio).OrderBy(x => x.Tag.TagName).Select(x => x.TagID).ToList();
|
|
|
|
}
|
|
}
|
|
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);
|
|
//if (scenario.Status == (int) ScenarioStatus.Active)
|
|
//{
|
|
var wfstate = wfManager.GetCurrentState(scenario.Id);
|
|
if (wfstate != null)
|
|
{
|
|
model.Parts[0].WorkFlowState = wfstate.state;
|
|
|
|
}
|
|
// }
|
|
}
|
|
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).Select(c => c.Id).ToList();
|
|
model.Parts[0].ExternalContacts = contacts.Where(c => c.Type == ContactType.ClientContact).Select(c => c.Id).ToList();
|
|
|
|
if (model.Parts[0].Attachments == null)
|
|
model.Parts[0].Attachments = new List<AttachmentModel>();
|
|
if (model.Parts[0].Links == null)
|
|
model.Parts[0].Links = new List<AttachmentModel>();
|
|
model.Parts[0].ProjectTags = new List<Guid>();
|
|
model.Parts[0].PortfolioTags = new List<Guid>();
|
|
model.Parts[0].WorkFlowContacts = new List<Guid>();
|
|
|
|
|
|
}
|
|
model.PartsCount = model.Parts.Count;
|
|
model.TrimStringProperties();
|
|
// SA. ENV-502. Attachments
|
|
if (model.PartsCount > 0)
|
|
{
|
|
if (model.PartsCount == 1 && model.Parts.First().Id.Equals(Guid.Empty))
|
|
{
|
|
// Project has no parts. Single existing in model part is virtual
|
|
// ENV-2379. It does not make sense to load anything for new project
|
|
if (!Guid.Empty.Equals(model.Id))
|
|
{
|
|
model.Parts[0].Attachments = dbContext.Attachments
|
|
.Where(x => x.ParentId.Equals(model.Id) && string.IsNullOrEmpty(x.Link) && string.IsNullOrEmpty(x.Link)).ToList().Select(y => (AttachmentModel)y).ToList();
|
|
model.Parts[0].Links = dbContext.Attachments
|
|
.Where(x => x.ParentId.Equals(model.Id) && !string.IsNullOrEmpty(x.Link) && !string.IsNullOrEmpty(x.Link)).ToList().Select(y => (AttachmentModel)y).ToList();
|
|
|
|
model.Parts[0].ProjectTags = dbContext.TagLinks.Where(x => x.ParentID == model.Id && x.TagLinkType == (int)TagType.Project).OrderBy(x => x.Tag.TagName).Select(x => x.TagID).ToList();
|
|
model.Parts[0].PortfolioTags = dbContext.TagLinks.Where(x => x.ParentID == model.Id && x.TagLinkType == (int)TagType.Portfolio).OrderBy(x => x.Tag.TagName).Select(x => x.TagID).ToList();
|
|
model.Parts[0].WorkFlowContacts = (new WorkFlowManager(dbContext)).GetContactList(model.Id, WorkFlowContactNotificationType.None);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Project has parts
|
|
var partIds = model.Parts.Select(x => x.Id);
|
|
IEnumerable<Attachment> allAttachments = dbContext.Attachments.AsNoTracking()
|
|
.Where(x => partIds.Contains(x.ParentId) && string.IsNullOrEmpty(x.Link));
|
|
IEnumerable<Attachment> allLinks = dbContext.Attachments.AsNoTracking()
|
|
.Where(x => partIds.Contains(x.ParentId) && !string.IsNullOrEmpty(x.Link));
|
|
foreach (ProjectPartModel part in model.Parts)
|
|
{
|
|
part.Attachments = allAttachments.Where(x => x.ParentId.Equals(part.Id)).ToList()
|
|
.Select(y => (AttachmentModel)y).ToList();
|
|
part.Links = allLinks.Where(x => x.ParentId.Equals(part.Id)).ToList()
|
|
.Select(y => (AttachmentModel)y).ToList();
|
|
|
|
part.ProjectTags = dbContext.TagLinks.Where(x => x.ParentID == part.Id && x.TagLinkType == (int)TagType.Project).OrderBy(x => x.Tag.TagName).Select(x => x.TagID).ToList();
|
|
part.PortfolioTags = dbContext.TagLinks.Where(x => x.ParentID == part.Id && x.TagLinkType == (int)TagType.Portfolio).OrderBy(x => x.Tag.TagName).Select(x => x.TagID).ToList();
|
|
part.WorkFlowContacts = (new WorkFlowManager(dbContext)).GetContactList(part.Id, WorkFlowContactNotificationType.None);
|
|
}
|
|
}
|
|
|
|
}
|
|
var udfMan = new UDFManager(dbContext);
|
|
model.UserDefinedFields = udfMan.LoadCollection(model.Id, UserDefinedFieldDomain.Project);
|
|
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?.Replace("#", "") ?? Color;
|
|
dbObj.Priority = Priority;
|
|
dbObj.Probability = Probability / 100.0M;
|
|
dbObj.IsRevenueGenerating = IsRevenueGenerating;
|
|
dbObj.Deadline = Deadline;
|
|
dbObj.HasChildren = HasChildren;
|
|
dbObj.PerformanceYellowThreshold = PerformanceYellowThreshold / 100.0M;
|
|
dbObj.PerformanceRedThreshold = PerformanceRedThreshold / 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,
|
|
TeamsUsage = this.TeamsUsage,
|
|
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,
|
|
PortfolioTags = this.PortfolioTags,
|
|
ProjectTags = this.ProjectTags,
|
|
WorkFlowContacts = this.WorkFlowContacts,
|
|
UserDefinedFields = this.UserDefinedFields
|
|
};
|
|
}
|
|
|
|
public ProjectModel()
|
|
{
|
|
TeamsUsage = new Dictionary<Guid, ProjectTeamUsage>();
|
|
Parts = new List<ProjectPartModel>();
|
|
WorkFlowContacts = new List<Guid>();
|
|
UserDefinedFields = new List<UDFValueCollection>();
|
|
StrategicGoals = new List<Guid>();
|
|
Scenarios = new List<ScenarioTabModel>();
|
|
ProjectTags = new List<Guid>();
|
|
PortfolioTags = new List<Guid>();
|
|
InternalContacts = new List<Guid>();
|
|
ExternalContacts = new List<Guid>();
|
|
AssignedTeams = new List<Guid>();
|
|
}
|
|
|
|
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, 500, ErrorMessage = "Your priority must be a number from 1 to 500")]
|
|
public decimal 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; }
|
|
public Dictionary<Guid, ProjectTeamUsage> TeamsUsage { 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 int? PartNum { get; set; }
|
|
[UIHint("FileUploadModel")]
|
|
public IList<AttachmentModel> Attachments { get; set; }
|
|
[UIHint("FileLinkModel")]
|
|
public IList<AttachmentModel> Links { get; set; }
|
|
[Display(Name = "Portfolio/Product Labels")]
|
|
public List<Guid> PortfolioTags { get; set; }
|
|
[Display(Name = "Project Tags")]
|
|
public List<Guid> ProjectTags { get; set; }
|
|
[Display(Name = "Workflow Contacts")]
|
|
public List<Guid> WorkFlowContacts { get; set; }
|
|
[Display(Name = "Workflow State")]
|
|
public string WorkFlowState { get; set; }
|
|
/// <summary>
|
|
/// Gets or sets a collection of project dependencies.
|
|
/// </summary>
|
|
[Display(Name = "Project Dependencies")]
|
|
public ProjectDependencies.ProjectDependencyListModel Dependencies { 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,
|
|
AssignedTeams = obj.Team2Project.Select(t2p => t2p.TeamId).ToList(),
|
|
StrategicGoals = obj.StrategicGoal2Project.Select(s2p => s2p.StrategicGoalId).ToList()
|
|
};
|
|
|
|
var contacts = obj.Contact2Project.Where(x => x.Contact != null).Select(c2p => c2p.Contact);
|
|
model.InternalContacts = contacts.Where(c => c.Type == ContactType.CompanyContact).Select(c => c.Id).ToList();
|
|
model.ExternalContacts = contacts.Where(c => c.Type == ContactType.ClientContact).Select(c => c.Id).ToList();
|
|
|
|
if (model.Attachments == null)
|
|
model.Attachments = new List<AttachmentModel>();
|
|
if (model.Links == null)
|
|
model.Links = 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,
|
|
TeamsUsage = this.TeamsUsage,
|
|
StrategicGoals = this.StrategicGoals,
|
|
InternalContacts = this.InternalContacts,
|
|
ExternalContacts = this.ExternalContacts,
|
|
DeletedPart = this.DeletedPart,
|
|
IsProbability100 = this.IsProbability100,
|
|
ParentProjectId = this.ParentProjectId,
|
|
PerformanceRedThreshold = this.PerformanceRedThreshold,
|
|
PerformanceYellowThreshold = this.PerformanceYellowThreshold,
|
|
PartNum = this.PartNum,
|
|
Attachments = this.Attachments,
|
|
ProjectTags = this.ProjectTags,
|
|
PortfolioTags = this.PortfolioTags,
|
|
WorkFlowContacts = this.WorkFlowContacts,
|
|
Links = this.Links
|
|
};
|
|
}
|
|
|
|
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(string.Format(Constants.ERROR_DEADLINE_DATE_LATE, Name), new[] { "Deadline" });
|
|
}
|
|
}
|
|
|
|
public ProjectPartModel()
|
|
{
|
|
Attachments = new List<AttachmentModel>();
|
|
Links = new List<AttachmentModel>();
|
|
PortfolioTags = new List<Guid>();
|
|
ProjectTags = new List<Guid>();
|
|
WorkFlowContacts = new List<Guid>();
|
|
}
|
|
}
|
|
|
|
/// <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 decimal 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; } = string.Empty;
|
|
public string Team { get; set; }
|
|
public Guid TeamId { get; set; }
|
|
public bool WritePermissionEnabledForCurrentUser { get; set; }
|
|
public ScenarioInProjectModel ActiveScenario { get; set; }
|
|
public List<InactiveScenarioInProjectModel> 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 bool ReadOnly { 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 InactiveScenarioInProjectModel : ScenarioInProjectModel
|
|
{
|
|
public long? StartDate { get; set; }
|
|
public long? EndDate { get; set; }
|
|
}
|
|
|
|
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; }
|
|
|
|
public Guid? PeopleResourceID { get; set; }
|
|
}
|
|
public class ProjectWithChildrenView
|
|
{
|
|
public Guid Id { get; set; }
|
|
public Guid? CompanyId { get; set; }
|
|
public string CompanyName { get; set; }
|
|
public Guid? ClientId { get; set; }
|
|
public string ClientName { get; set; }
|
|
public string Name { get; set; }
|
|
public string TypeName { get; set; }
|
|
public DateTime? Deadline { get; set; }
|
|
public decimal Priority { get; set; }
|
|
public bool HasChildren { get; set; }
|
|
public string Color { get; set; }
|
|
public bool ReadOnly { get; set; }
|
|
public Guid StatusId { get; set; }
|
|
public Guid TypeId { get; set; }
|
|
public string StatusName { get; set; }
|
|
public decimal Probability { get; set; }
|
|
public Guid? ParentProjectId { get; set; }
|
|
public decimal? PerformanceYellowThreshold { get; set; }
|
|
public decimal? PerformanceRedThreshold { get; set; }
|
|
|
|
public List<Guid> Teams { get; set; }
|
|
public List<Guid> StrategicGoals { get; set; }
|
|
public ParentProjectView ParentProject { get; set; }
|
|
public List<ScenarioView> Scenarios { get; set; }
|
|
|
|
#region Internal Classes
|
|
|
|
public class ParentProjectView
|
|
{
|
|
public Guid Id { get; set; }
|
|
public Guid? CompanyId { get; set; }
|
|
public string Name { get; set; }
|
|
public string Color { get; set; }
|
|
}
|
|
|
|
public class ScenarioView
|
|
{
|
|
public Guid Id { get; set; }
|
|
public Guid? ParentId { get; set; }
|
|
public string Name { get; set; }
|
|
public bool IsBottomUp { get; set; }
|
|
public ScenarioStatus? Status { get; set; }
|
|
public ScenarioType? Type { get; set; }
|
|
public DateTime? StartDate { get; set; }
|
|
public DateTime? EndDate { get; set; }
|
|
public DateTime? DateCreated { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |