public override List <TimeLog> LoadData(TimeLogReportingServiceContext context) { string iterationPath = context.IterationPath; //var estimatedEndDate = context.GetMilestone(CodeCompletionDate); var wiStore = Connect(context).GetService <WorkItemStore>(); //get linked work items //http://blogs.msdn.com/b/jsocha/archive/2012/02/22/retrieving-tfs-results-from-a-tree-query.aspx Query treeQuery = PrepareTreeQuery(wiStore, iterationPath, context.Project.Title); WorkItemLinkInfo[] links = treeQuery.RunLinkQuery(); WorkItemCollection linkedResults = GetAssociatedWorkItems(wiStore, treeQuery, links); var linkedList = ConvertToTimeTrackingDetails(linkedResults); var relationMap = BuildRelationMap(linkedList, links); //get unlinked workitems WorkItemCollection results = GetAllWorkItems(wiStore, iterationPath, context.Project.Title); var list = ConvertToTimeTrackingDetails(results); var idList = relationMap.Select(q => q.WorkitemId).ToList(); relationMap.AddRange(list.Where(p => !idList.Contains(p.WorkitemId))); SkipSpecificTitlePBIs(relationMap); return(relationMap); }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (string.Compare(workitem.Type, ProductBacklogItem, true) == 0) { //get atleast one "IMPACT ANALYSIS" task assigned to anyone const string AnalysisTaskTitle = "IMPACT ANALYSIS"; var analysisTasks = workitem.Tasks.Where(q => q.Title.ToUpper().IndexOf(AnalysisTaskTitle) >= 0).ToList(); if (analysisTasks.Count > 0) { analysisTasks.ForEach(p => p.Owner = TaskOwnerType.Team); } else { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Impact Analysis task not created yet", AssignedTo = workitem.AssignedTo }); } //get atleast one "touch points" task assigned to anyone (optional) const string TouchPointTaskTitle = "TOUCH POINT"; var touchPointTasks = workitem.Tasks.Where(q => q.Title.ToUpper().IndexOf(TouchPointTaskTitle) >= 0).ToList(); if (touchPointTasks.Count > 0) { touchPointTasks.ForEach(p => p.Owner = TaskOwnerType.Team); } } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (workitem.PlannedDevEfforts == 0) { //get first developer var assignedToDev = workitem.Tasks.Where(p => p.Owner == TaskOwnerType.Developer).FirstOrDefault(); workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Dev estimates are missing.", AssignedTo = assignedToDev != null ? assignedToDev.AssignedTo : string.Empty }); } if (workitem.PlannedQAEfforts == 0) { //get first QA var assignedToQA = workitem.Tasks.Where(p => p.Owner == TaskOwnerType.Tester).FirstOrDefault(); workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "QA estimates are missing.", AssignedTo = assignedToQA != null ? assignedToQA.AssignedTo : string.Empty }); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { ValidateByrole(context, workitem, TaskOwnerType.Architect, "Architect code review"); ValidateByrole(context, workitem, TaskOwnerType.Peer, "Peer code review"); ValidateByrole(context, workitem, TaskOwnerType.Developer, "Development"); ValidateByrole(context, workitem, TaskOwnerType.Tester, "Testing"); ValidateByrole(context, workitem, TaskOwnerType.Team, "Generic"); }
//check if current assigned person is developer private static string GetAssignedToIfDeveloper(TimeLogReportingServiceContext context, string assignedTo) { if (context.TeamProfiles != null && context.TeamProfiles.Count > 0) { if (context.TeamProfiles.Where(p => string.Compare(p.Fullname, assignedTo, true) == 0 && string.Compare(p.Role, TaskOwnerType.Developer.ToString(), true) == 0).Any()) { return(assignedTo); } } return(string.Empty); }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (string.IsNullOrEmpty(workitem.DevelopmentTracking) == true) { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Development Tracking value not set.", AssignedTo = workitem.AssignedTo }); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (workitem.Tasks.Where(q => string.IsNullOrEmpty(q.AssignedTo) == true).Any()) { workitem.Observations.Add(new Observation { Code = "Mismatch", Title = "There are one or more unassigned tasks created for this workitem.", AssignedTo = workitem.AssignedTo //TODO: Logic to identify assignedTo }); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (workitem.Tasks == null || workitem.Tasks.Count == 0) { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Tasks not created under this PBI", AssignedTo = workitem.AssignedTo }); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { var query = workitem.Tasks.Where(p => p.IterationPath != workitem.IterationPath); if (workitem.Tasks == null || query.Any()) { Rolewise(workitem, query, TaskOwnerType.Architect, "architect code review"); Rolewise(workitem, query, TaskOwnerType.Peer, "peer code review"); Rolewise(workitem, query, TaskOwnerType.Developer, "development"); Rolewise(workitem, query, TaskOwnerType.Tester, "testing"); Rolewise(workitem, query, TaskOwnerType.Team, "generic"); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (string.Compare(workitem.Type, ProductBacklogItem, true) == 0) { var codeCompletionDate = context.GetMilestone("Code Completion Date"); var reviewCompletionDate = context.GetMilestone("Code Review Completion Date"); var qaCompletionDate = context.GetMilestone("QA Completion Date"); ValidateCodeCompleteMilestone(workitem, codeCompletionDate); ValidateCodeReviewMilestone(workitem, reviewCompletionDate); ValidateQAMilestone(workitem, qaCompletionDate); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (string.Compare(workitem.Type, ProductBacklogItem, true) == 0) { if (string.Compare(workitem.State, "Committed", true) != 0 && string.Compare(workitem.State, "Done", true) != 0) { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "The PBI is not marked Committed or Done.", AssignedTo = workitem.AssignedTo }); } } }
private void ValidateByrole(TimeLogReportingServiceContext context, TimeLog workitem, TaskOwnerType taskowner, string taskTypes) { var teamMembers = context.TeamProfiles.Where(p => string.Compare(p.Role, taskowner.ToString(), true) == 0).Select(p => p.Fullname.ToLower()).ToList(); workitem.Tasks.Where(p => p.Owner == taskowner).ToList().ForEach(p => { if (teamMembers.Where(q => teamMembers.Contains(q.ToLower()) == false).Any()) { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = string.Format("One or more {0} tasks are not assigned to respective {1}s", taskTypes, taskowner), AssignedTo = workitem.AssignedTo }); } }); }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (workitem.ActualDevEfforts - workitem.Tasks.Where(p => p.Owner == TaskOwnerType.Developer).Sum(q => q.ActualDevEfforts) != 0) { workitem.Observations.Add(new Observation { Code = "Mismatch", Title = "Workitem and task level actual efforts (Dev) do not match.", AssignedTo = GetOwnerName(workitem, TaskOwnerType.Developer) }); } if (workitem.PlannedDevEfforts - workitem.Tasks.Where(p => p.Owner == TaskOwnerType.Developer).Sum(q => q.PlannedDevEfforts) != 0) { workitem.Observations.Add(new Observation { Code = "Mismatch", Title = "Workitem and task level planned efforts (Dev) do not match.", AssignedTo = GetOwnerName(workitem, TaskOwnerType.Developer) }); } //Note task level efforts for QA and Dev are all set in the DevEfforts fields if (workitem.ActualQAEfforts - workitem.Tasks.Where(p => p.Owner == TaskOwnerType.Tester).Sum(q => q.ActualDevEfforts) != 0) { workitem.Observations.Add(new Observation { Code = "Mismatch", Title = "Workitem and task level planned efforts (QA) do not match.", AssignedTo = GetOwnerName(workitem, TaskOwnerType.Tester) }); } if (workitem.PlannedQAEfforts - workitem.Tasks.Where(p => p.Owner == TaskOwnerType.Tester).Sum(q => q.PlannedDevEfforts) != 0) { workitem.Observations.Add(new Observation { Code = "Mismatch", Title = "Workitem and task level planned efforts (QA) do not match.", AssignedTo = GetOwnerName(workitem, TaskOwnerType.Tester) }); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { const string PeerCodeReviewTaskTitle = "PEER CODE REVIEW"; //get atleast one "PEER CODE REVIEW" task assigned to anyone var peerCodeReviewTasks = workitem.Tasks.Where(q => q.Title.ToUpper().IndexOf(PeerCodeReviewTaskTitle) >= 0).ToList(); if (peerCodeReviewTasks.Count > 0) { peerCodeReviewTasks.ForEach(p => p.Owner = TaskOwnerType.Peer); } else { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Peer code review task not created yet. Please contact respective peer.", AssignedTo = workitem.AssignedTo //TODO: Logic to identify peer reviewer }); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { const string FunctionalTestingTaskTitle = "FUNCTIONAL TESTING"; //get atleast one "FUNCTIONAL TESTING" task assigned to anyone var testingTasks = workitem.Tasks.Where(q => q.Title.ToUpper().IndexOf(FunctionalTestingTaskTitle) >= 0).ToList(); if (testingTasks.Count > 0) { testingTasks.ForEach(p => p.Owner = TaskOwnerType.Tester); } else { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Functional testing task not created yet. Please contact respective QA", AssignedTo = GetAssignedToIfTester(context, workitem.AssignedTo) }); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { var taskDoneButNoTimeQuery = workitem.Tasks.Where(q => q.IsTaskMarkedAsDone == true && q.ActualDevEfforts == 0 && q.Owner != TaskOwnerType.Team); if (taskDoneButNoTimeQuery.Any()) { workitem.Observations.Add(new Observation { Code = "Mismatch", Title = "There is atleast one task marked completed, but no time logged under it." }); taskDoneButNoTimeQuery.ToList().ForEach(p => { p.Observations.Add(new Observation { Code = "Mismatch", Title = string.Format("Task #{0} is marked completed but has no time logged under it.", p.WorkitemId), AssignedTo = p.AssignedTo }); }); } var incompleteTaskNoRemainingTimeQuery = workitem.Tasks.Where(q => q.RemainingWork == null && q.IsTaskMarkedAsDone == false); if (incompleteTaskNoRemainingTimeQuery.Any()) { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Atleast one of the incomplete task is missing remaining work" }); incompleteTaskNoRemainingTimeQuery.ToList().ForEach(p => { p.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = string.Format("Task #{0} is incomplete but does not have remaining work", p.WorkitemId), AssignedTo = p.AssignedTo }); }); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (string.Compare(workitem.Type, ProductBacklogItem, true) == 0) { const string TestcaseWritingTaskTitle = "TC WRITING"; var testingTasks = workitem.Tasks.Where(q => q.Title.ToUpper().IndexOf(TestcaseWritingTaskTitle) >= 0).ToList(); if (testingTasks.Count > 0) { testingTasks.ForEach(p => p.Owner = TaskOwnerType.Tester); } else { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "TC Writing task not created yet. Please contact respective QA", AssignedTo = workitem.AssignedTo //TODO: Logic to identify tester }); } } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (string.Compare(workitem.Type, Bug, true) == 0) { const string CodingTaskTitle = "CODING"; var unitTestTasks = workitem.Tasks.Where(q => q.Title.ToUpper().IndexOf(CodingTaskTitle) >= 0).ToList(); if (unitTestTasks.Count > 0) { unitTestTasks.ForEach(p => p.Owner = TaskOwnerType.Developer); } else { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Coding task not created yet.", AssignedTo = GetAssignedToIfDeveloper(context, workitem.AssignedTo) }); } } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (string.Compare(workitem.Type, ProductBacklogItem, true) == 0) { const string ArchitectReviewTaskTitle = "ARCHITECT CODE REVIEW"; //get atleast one "ARCHITECT CODE REVIEW" task assigned to anyone var architectCodeReviewTasks = workitem.Tasks.Where(q => q.Title.ToUpper().IndexOf(ArchitectReviewTaskTitle) >= 0).ToList(); if (architectCodeReviewTasks.Count > 0) { architectCodeReviewTasks.ForEach(p => p.Owner = TaskOwnerType.Architect); } else { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Architect code review task not created yet. Please contact respective architect/Lead", AssignedTo = workitem.AssignedTo //TODO: Logic to identify architect }); } } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { if (string.Compare(workitem.Type, ProductBacklogItem, true) == 0) { const string UnitTestingTaskTitle = "UNIT TESTING"; //get atleast one "UNIT TESTING" task assigned to ME var unitTestTasks = workitem.Tasks.Where(q => q.Title.ToUpper().IndexOf(UnitTestingTaskTitle) >= 0).ToList(); if (unitTestTasks.Count > 0) { unitTestTasks.ForEach(p => p.Owner = TaskOwnerType.Developer); } else { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Unit testing task not created yet.", AssignedTo = workitem.AssignedTo }); } } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { var query = workitem.Tasks.Where(q => q.Title.StartsWith(workitem.WorkitemId.ToString()) == false); if (query.Any()) { workitem.Observations.Add(new Observation { Code = "Naming convention", Title = "At least one task title does not start with PBI number.", }); query.ToList().ForEach(p => { p.Observations.Add(new Observation { Code = "Naming convention", Title = string.Format("Title of task #{0} does not start with PBI number.", p.WorkitemId), AssignedTo = p.AssignedTo }); }); } }
public override void Analyze(TimeLogReportingServiceContext context, TimeLog workitem) { //development tasks var query = workitem.Tasks.Where(p => p.Owner == TaskOwnerType.Developer && string.Compare(p.Activity, "Development", true) != 0); if (query.Any()) { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "One or more developer tasks do not have the right \"Activity\" (Development)." }); query.ToList().ForEach(p => { p.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = string.Format("Developer task #{0} does not have the right \"Activity\" (Development).", p.WorkitemId), AssignedTo = p.AssignedTo, WorkitemId = p.WorkitemId }); }); } //QA tasks query = workitem.Tasks.Where(p => p.Owner == TaskOwnerType.Tester && string.Compare(p.Activity, "Testing", true) != 0); if (query.Any()) { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "One or more tester tasks do not have the right \"Activity\" (Testing)." }); query.ToList().ForEach(p => { p.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = string.Format("Testing task #{0} does not have the right \"Activity\" (Testing).", p.WorkitemId), AssignedTo = p.AssignedTo, WorkitemId = p.WorkitemId }); }); } //peer review task query = workitem.Tasks.Where(p => (p.Owner == TaskOwnerType.Peer) && string.Compare(p.Activity, "Design", true) != 0); if (query.Any()) { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Peer review task does not have the right \"Activity\" (Design)." }); query.ToList().ForEach(p => { p.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = string.Format("Peer review task #{0} does not have the right \"Activity\" (Design).", p.WorkitemId), AssignedTo = p.AssignedTo, WorkitemId = p.WorkitemId }); }); } //architect review task query = workitem.Tasks.Where(p => (p.Owner == TaskOwnerType.Architect) && string.Compare(p.Activity, "Design", true) != 0); if (query.Any()) { workitem.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = "Architect review task does not have the right \"Activity\" (Design)." }); query.ToList().ForEach(p => { p.Observations.Add(new Observation { Code = "Lifecycle checklist", Title = string.Format("Architect review task #{0} does not have the right \"Activity\" (Design).", p.WorkitemId), AssignedTo = p.AssignedTo, WorkitemId = p.WorkitemId }); }); } }