private Project GetProject(SchedulingEntities context, int ProjectID) { if (!projects.ContainsKey(ProjectID)) { var project = (from p in context.ProjectView where p.ShadowPID == ProjectID select p).FirstOrDefault(); if (project == null) { throw new Exception(string.Format("Invalid ProjectID: {0}", ProjectID)); } projects.Add(ProjectID, new Project() { ProjectId = ProjectID, ProjectName = project.Name, Parent = GetClient(context, project.ShadowCLID), HoursEstimated = project.EstimatedDuration ?? 0.0d, HoursRecorded = GetAllTimeForProject(context, ProjectID) }); } return projects[ProjectID]; }
private Client GetClient(SchedulingEntities context, int ClientID) { if (!clients.ContainsKey(ClientID)) { var client = (from c in context.ClientView where c.ShadowCLID == ClientID select c).FirstOrDefault(); if (client == null) { throw new Exception(string.Format("Invalid Client ID: {0}", ClientID)); } clients.Add(ClientID, new Client() { ClientId = ClientID, ClientName = client.Name }); } return clients[ClientID]; }
/* private double GetHoursForProjectByResource(SchedulingEntities context, int ProjectId, string resourceId, DateTime start, DateTime end) { // Yes... the performance here is terribad. Fixme. Also validate that the logic is correct. var query = from te in context.TimeEntryView where te.EmployeeID == resourceId && (te.H1 == ProjectId || te.H2 == ProjectId || te.H3 == ProjectId || te.H4 == ProjectId || te.H5 == ProjectId || te.H6 == ProjectId || te.H7 == ProjectId || te.H8 == ProjectId) && (te.EntryDate.Value >= start // Should have logic errors at the edge cases, && te.EntryDate.Value <= end) // need to make sure this matches on date alone without time component. select te.EntryTime; return SumTimeEntries(query); } */ private static double GetAllTimeForProject(SchedulingEntities context, int ProjectID) { var query = from te in context.TimeEntryView where te.H1 == ProjectID || te.H2 == ProjectID || te.H3 == ProjectID || te.H4 == ProjectID || te.H5 == ProjectID || te.H6 == ProjectID || te.H7 == ProjectID || te.H8 == ProjectID select te.EntryTime; return SumTimeEntries(query); }
public List<SchedulerView> GetScheduleView(SchedulingEntities context, DateTime start, DateTime end) { var query = from row in context.SchedulerView where row.Week >= start.Date && row.Week <= end.Date orderby row.UserID select row; return query.ToList(); }
public IList<ProjectHoursRollup> GetProjectHoursRollup(SchedulingEntities context, string resourceId, DateTime start, DateTime end) { // Let's see how well this works if we say that generally, we want H1 for this and don't want any further detail. // This should give us the highest level project for this time entry. For instance, we would fetch the Product Development PID under Yahara Software LLC var query = from entries in context.yps_GetTimeEntriesInRange(resourceId, start, end) //group entries by entries.ShadowPID into egrp group entries by entries.H1 ?? -1 into egrp select new ProjectHoursRollup { ProjectID = egrp.Key, ResourceID = resourceId, ClientID = (from i in egrp select i).FirstOrDefault().ShadowCLID, BillableHours = (from i in egrp where i.Billable select i.Time ?? 0).Sum(), NonBillableHours = (from i in egrp where !i.Billable select i.Time ?? 0).Sum(), }; return query.ToList(); }
/// <summary> /// Build a forecast all nasty style. Refactor this later when we know what we really want. /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> public ForecastSummary GetForecast(string sStart, string sEnd) { DateTime start = sStart.StringToDateTime(); DateTime end = sEnd.StringToDateTime(); using (var context = new SchedulingEntities()) { var results = new List<ResourceSummary>(); string currentUser = string.Empty; ResourceSummary current = null; var scheduleView = GetScheduleView(context, start, end); var resourceIds = (from item in scheduleView select item.EmployeeID).Distinct(); foreach (var resourceId in resourceIds) { // for each distinct resource set up a ResourceSummary if (current == null || current.Resource == null || current.Resource.UserId != resourceId) { // The summary view has some generic stuff we need the first time we set up a dude var viewRecord = scheduleView.Where(v => v.EmployeeID == resourceId).First(); current = new ResourceSummary(); results.Add(current); current.Resource = GetResource(viewRecord); current.StartDate = viewRecord.Week; } // Next we need to take a combination of what the resource was scheduled for, against what they have recorded in webshadow. Dictionary<int, ProjectHoursRollup> projectHours = GetProjectHoursRollup(context, resourceId, start, end).ToDictionary(dk => dk.ProjectID); foreach (var scheduleItem in (from sv in scheduleView where sv.EmployeeID == resourceId select sv)) { int id = int.Parse(scheduleItem.AppProjectID); if (projectHours.ContainsKey(id)) { projectHours[id].HoursScheduled = (double)scheduleItem.ForecastHours; } else { projectHours.Add(id, new ProjectHoursRollup() { BillableHours = 0, NonBillableHours = 0, HoursScheduled = (double)scheduleItem.ForecastHours, ProjectID = id, ResourceID = resourceId, ClientID = scheduleItem.ClientID }); } } foreach (var projectItem in projectHours.Values.OrderBy(ph => ph.IsScheduled)) { current.TotalHoursRecorded += projectItem.TotalHoursRealized; current.TotalHoursScheduled += projectItem.HoursScheduled; current.BillableHoursScheduled += projectItem.BillableHours; current.Assignments.Add(new ScheduledAssignment() { AssignedProject = GetProject(context, projectItem.ProjectID), AssignedResource = current.Resource, HoursScheduled = projectItem.HoursScheduled, HoursRecorded = projectItem.TotalHoursRealized, IsScheduled = projectItem.IsScheduled }); } } var summary = new ForecastSummary() { BillableHoursScheduled = (from rs in results select rs.BillableHoursScheduled).Sum(), TotalHoursScheduled = (from rs in results select rs.TotalHoursScheduled).Sum(), EndDate = end, StartDate = start, Resources = results }; ScheduledAssignment.ScheduledFirstSorter sorter = new ScheduledAssignment.ScheduledFirstSorter(); foreach (var rs in summary.Resources) { rs.Assignments.Sort(sorter); } return summary; } }