public static List <ARmUnit> ExpandUnit(RMReportReader report, RMDataSource ds, ARmUnit unit, object startKey, object endKey, Func <ARmDataSet, List <T> > fetchRangePredicate, Func <T, string> unitCodePredicate, Func <T, string> unitDescriptionPredicate, Action <T, string> applyWildcardToItemAction) { string nonExpandingWildcard = null; PreProcessNonExpandingWildcardChar(unit.DataSet, startKey, out nonExpandingWildcard); //This will validate Start/End range and merge the pair into a single range-like value that FillSubsList expects. ARmDataSet rangeToFetch = new ARmDataSet(); RMReportWildcard.ConcatenateRangeWithDataSet(rangeToFetch, unit.DataSet, startKey, endKey, MergingMode.Intersection); List <T> unitItems = fetchRangePredicate(rangeToFetch); if (nonExpandingWildcard != null) { //TODO: Build a better auto-description based on segment values instead of copying code to description? unitItems = ReduceListByNonExpandingWildcard(nonExpandingWildcard, unitItems, (u) => unitCodePredicate(u), (u, mv) => applyWildcardToItemAction(u, mv)); } switch (ds.RowDescription.Trim().ToUpper()) { case RowDescriptionType.CodeDescription: unitItems.Sort((x, y) => (unitCodePredicate(x) + unitDescriptionPredicate(x)).CompareTo(unitCodePredicate(y) + unitDescriptionPredicate(y))); break; case RowDescriptionType.DescriptionCode: unitItems.Sort((x, y) => (unitDescriptionPredicate(x) + unitCodePredicate(x)).CompareTo(unitDescriptionPredicate(y) + unitCodePredicate(y))); break; case RowDescriptionType.Description: unitItems.Sort((x, y) => unitDescriptionPredicate(x).CompareTo(unitDescriptionPredicate(y))); break; default: unitItems.Sort((x, y) => unitCodePredicate(x).CompareTo(unitCodePredicate(y))); break; } List <ARmUnit> units = new List <ARmUnit>(); int n = 0; foreach (T unitItem in unitItems) { n++; var u = new ARmUnit(); report.FillDataSource(ds, u.DataSet, report.Report.Current.Type); u.DataSet[startKey] = unitCodePredicate(unitItem); u.DataSet[endKey] = null; u.Code = unit.Code + n.ToString("D5"); switch (ds.RowDescription.Trim()) { case RowDescriptionType.CodeDescription: u.Description = string.Format("{0}{1}{2}", unitCodePredicate(unitItem).Trim(), "-", unitDescriptionPredicate(unitItem)); break; case RowDescriptionType.DescriptionCode: u.Description = string.Format("{0}{1}{2}", unitDescriptionPredicate(unitItem), "-", unitCodePredicate(unitItem).Trim()); break; case RowDescriptionType.Description: u.Description = unitDescriptionPredicate(unitItem); break; default: u.Description = unitCodePredicate(unitItem).Trim(); break; } u.Formula = unit.Formula; u.PrintingGroup = unit.PrintingGroup; units.Add(u); } return(units); }
public virtual List <ARmUnit> ExpandUnit(RMDataSource ds, ARmUnit unit, Func <RMDataSource, ARmUnit, List <ARmUnit> > del) { string rmType = Base.Report.Current.Type; if (rmType == ARmReport.PM) { if (unit.DataSet.Expand != ExpandType.Nothing) { PMEnsureInitialized(); if (ds.Expand == ExpandType.AccountGroup) { return(RMReportUnitExpansion <PMAccountGroup> .ExpandUnit(Base, ds, unit, Keys.StartAccountGroup, Keys.EndAccountGroup, rangeToFetch => _accountGroupsRangeCache.GetItemsInRange(rangeToFetch[Keys.StartAccountGroup] as string, accountGroup => accountGroup.GroupCD, (accountGroup, code) => accountGroup.GroupCD = code), accountGroup => accountGroup.GroupCD, accountGroup => accountGroup.Description, (accountGroup, wildcard) => { accountGroup.GroupCD = wildcard; accountGroup.Description = wildcard; })); } else if (ds.Expand == ExpandType.Project) { return(RMReportUnitExpansion <PMProject> .ExpandUnit(Base, ds, unit, Keys.StartProject, Keys.EndProject, rangeToFetch => _projectsRangeCache.GetItemsInRange(rangeToFetch[Keys.StartProject] as string, project => project.ContractCD, (project, code) => project.ContractCD = code), project => project.ContractCD, project => project.Description, (project, wildcard) => { project.ContractCD = wildcard; project.Description = wildcard; })); } else if (ds.Expand == ExpandType.ProjectTask) { return(RMReportUnitExpansion <PMTask> .ExpandUnit(Base, ds, unit, Keys.StartProjectTask, Keys.EndProjectTask, rangeToFetch => { List <PMTask> tasks = _tasksRangeCache.GetItemsInRange(rangeToFetch[Keys.StartProjectTask] as string, task => task.TaskCD, (task, code) => task.TaskCD = code); ARmDataSet projectRange = new ARmDataSet(); RMReportWildcard.ConcatenateRangeWithDataSet(projectRange, unit.DataSet, Keys.StartProject, Keys.EndProject, MergingMode.Intersection); if (!String.IsNullOrEmpty(projectRange[Keys.StartProject] as string)) { //A project range is specified in the unit; restrict tasks to tasks of this project range. List <PMProject> projects = _projectsRangeCache.GetItemsInRange(projectRange[Keys.StartProject] as string, project => project.ContractCD, (project, code) => project.ContractCD = code); tasks = tasks.Where(t => projects.Any(p => t.ProjectID == p.ContractID)).ToList <PMTask>(); } //Same project TaskCD can be reused in multiple projects; it only makes sense to get distinct values for the purpose of filling the unit tree List <PMTask> groupedTasks = tasks.GroupBy(t => t.TaskCD).Select(g => new PMTask() { TaskCD = g.Key, Description = g.Min(t => t.Description) }).ToList <PMTask>(); return groupedTasks; }, task => task.TaskCD, project => project.Description, (task, wildcard) => { task.TaskCD = wildcard; task.Description = wildcard; })); } else if (ds.Expand == ExpandType.Inventory) { return(RMReportUnitExpansion <InventoryItem> .ExpandUnit(Base, ds, unit, Keys.StartInventory, Keys.EndInventory, rangeToFetch => _itemRangeCache.GetItemsInRange(rangeToFetch[Keys.StartInventory] as string, item => item.InventoryCD, (item, code) => item.InventoryCD = code), item => item.InventoryCD, item => item.Descr, (item, wildcard) => { item.InventoryCD = wildcard; item.Descr = wildcard; })); } } } else { return(del(ds, unit)); } return(null); }