private static void PreProcessNonExpandingWildcardChar(ARmDataSet dataSet, object key, out string nonExpandingWildcard) { bool hasWildcard = false; string originalValue = (dataSet[key] as string ?? ""); StringBuilder processedValue = new StringBuilder(originalValue.Length); for (int i = 0; i < originalValue.Length; i++) { if (originalValue[i] == RMReportConstants.NonExpandingWildcardChar) { processedValue.Append(RMReportConstants.DefaultWildcardChar); hasWildcard = true; } else { processedValue.Append(originalValue[i]); } } if (hasWildcard == true) { dataSet[key] = processedValue.ToString(); nonExpandingWildcard = originalValue; } else { nonExpandingWildcard = null; } }
public ARmDataSet MergeDataSet(IEnumerable <ARmDataSet> list, string expand, MergingMode mode, Func <IEnumerable <ARmDataSet>, string, MergingMode, ARmDataSet> del) { ARmDataSet dataSet = del(list, expand, mode); string rmType = Base.Report.Current.Type; if (rmType == ARmReport.PM) { foreach (ARmDataSet set in list) { if (set == null) { continue; } RMReportWildcard.ConcatenateRangeWithDataSet(dataSet, set, Keys.StartAccountGroup, Keys.EndAccountGroup, mode); RMReportWildcard.ConcatenateRangeWithDataSet(dataSet, set, Keys.StartProject, Keys.EndProject, mode); RMReportWildcard.ConcatenateRangeWithDataSet(dataSet, set, Keys.StartProjectTask, Keys.EndProjectTask, mode); RMReportWildcard.ConcatenateRangeWithDataSet(dataSet, set, Keys.StartInventory, Keys.EndInventory, mode); } dataSet.Expand = list.First().Expand; } return(dataSet); }
public void FillDataSource(RMDataSource ds, ARmDataSet dst, string rmType, Action <RMDataSource, ARmDataSet, string> del) { del(ds, dst, rmType); if (rmType == ARmReport.PM) { FillDataSourceInternal(ds, dst, rmType); } }
private void FillDataSourceInternal(RMDataSource ds, ARmDataSet dst, string rmType) { if (ds != null && ds.DataSourceID != null) { RMDataSourcePM dsPM = Base.Caches[typeof(RMDataSource)].GetExtension <RMDataSourcePM>(ds); dst[Keys.StartAccountGroup] = dsPM.StartAccountGroup; dst[Keys.EndAccountGroup] = dsPM.EndAccountGroup; dst[Keys.StartProject] = dsPM.StartProject; dst[Keys.EndProject] = dsPM.EndProject; dst[Keys.StartProjectTask] = dsPM.StartProjectTask; dst[Keys.EndProjectTask] = dsPM.EndProjectTask; dst[Keys.StartInventory] = dsPM.StartInventory; dst[Keys.EndInventory] = dsPM.EndInventory; } }
public bool IsParameter(ARmDataSet ds, string name, ValueBucket value, Func <ARmDataSet, string, ValueBucket, bool> del) { bool flag = del(ds, name, value); if (!flag) { Keys key; if (_keysDictionary.TryGetValue(name, out key)) { value.Value = ds[key]; return(true); } return(false); } return(flag); }
public static void ConcatenateRangeWithDataSet(ARmDataSet target, ARmDataSet source, object startKey, object endKey, MergingMode mergingMode) { string startValue = (source[startKey] as string ?? String.Empty); string endValue = (source[endKey] as string ?? String.Empty); char mergeChar = default(char); switch (mergingMode) { case MergingMode.Intersection: mergeChar = RMReportConstants.RangeIntersectionChar; break; case MergingMode.Union: mergeChar = RMReportConstants.RangeUnionChar; break; default: throw new NotSupportedException(PXMessages.LocalizeFormatNoPrefixNLA(Messages.MergingModeNotSupported, mergingMode)); } if (!(startValue == String.Empty && endValue == String.Empty)) { if (startValue.Contains(RMReportConstants.RangeDelimiterChar) && endValue != String.Empty) { throw new ArgumentException(PXMessages.LocalizeFormatNoPrefixNLA(Messages.ValueShouldBeEmpty, startKey, startValue, endKey, endValue)); } else if (startValue == String.Empty && endValue != String.Empty) { throw new ArgumentException(PXMessages.LocalizeFormatNoPrefixNLA(Messages.DataSourceIncomplete, endKey, startKey, endValue)); } if (!String.IsNullOrEmpty(target[startKey] as string)) { // There's existing data stored; we will intersect/union previous range with this new range at a later stage target[startKey] += mergeChar.ToString(); } target[startKey] += startValue; if (endValue != String.Empty) { target[startKey] += RMReportConstants.RangeDelimiterChar.ToString() + endValue; } } }
public static void ConcatenateRangeWithDataSet(ARmDataSet target, ARmDataSet source, object startKey, object endKey, MergingMode mergingMode) { string startValue = (source[startKey] as string ?? String.Empty); string endValue = (source[endKey] as string ?? String.Empty); char mergeChar = default(char); switch (mergingMode) { case MergingMode.Intersection: mergeChar = RMReportConstants.RangeIntersectionChar; break; case MergingMode.Union: mergeChar = RMReportConstants.RangeUnionChar; break; default: throw new NotSupportedException(String.Format("Merging mode '{0}' is not supported.", mergingMode)); } if (!(startValue == String.Empty && endValue == String.Empty)) { if (startValue.Contains(RMReportConstants.RangeDelimiterChar) && endValue != String.Empty) { throw new ArgumentException(String.Format("A range is specified in {0}; end value should be empty. {0}: {1}. {2}: {3}.", startKey, startValue, endKey, endValue)); } else if (startValue == String.Empty && endValue != String.Empty) { throw new ArgumentException(String.Format("Data Source is incomplete. If you set {0}, you should also define {1}. {0}: {2}.", endKey, startKey, endValue)); } if (!String.IsNullOrEmpty(target[startKey] as string)) { // There's existing data stored; we will intersect/union previous range with this new range at a later stage target[startKey] += mergeChar.ToString(); } target[startKey] += startValue; if (endValue != String.Empty) { target[startKey] += RMReportConstants.RangeDelimiterChar.ToString() + endValue; } } }
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); }
private object CalculateAndExpandValue(bool drilldown, RMDataSource ds, RMDataSourceGL dsGL, RMDataSourcePM dsPM, ARmDataSet dataSet, List <PMAccountGroup> accountGroups, List <PMProject> projects, List <PMTask> tasks, List <InventoryItem> items, List <object[]> splitret) { decimal totalAmount = 0; object locker = new object(); Dictionary <PMHistoryKeyTuple, PXResult <PMHistory, PMProject, PMTask, PMAccountGroup, InventoryItem> > drilldownData = null; if (drilldown) { drilldownData = new Dictionary <PMHistoryKeyTuple, PXResult <PMHistory, PMProject, PMTask, PMAccountGroup, InventoryItem> >(); } Parallel.For(0, accountGroups.Count, accountGroup => { PMAccountGroup currentAccountGroup = accountGroups[accountGroup]; if (!_historySegments.Contains(new PMHistoryKeyTuple(0, String.Empty, currentAccountGroup.GroupID.Value, 0))) { return; } Parallel.For(0, projects.Count, project => { PMProject currentProject = projects[project]; if (!_historySegments.Contains(new PMHistoryKeyTuple(currentProject.ContractID.Value, String.Empty, currentAccountGroup.GroupID.Value, 0))) { return; } Parallel.For(0, tasks.Count, task => { PMTask currentTask = tasks[task]; if (!_historySegments.Contains(new PMHistoryKeyTuple(currentProject.ContractID.Value, currentTask.TaskCD, currentAccountGroup.GroupID.Value, 0))) { return; } if (ds.Expand != ExpandType.ProjectTask && currentTask.ProjectID != currentProject.ContractID) { return; } Parallel.For(0, items.Count, item => { InventoryItem currentItem = items[item]; List <PMHistory> periods = GetPeriodsToCalculate(currentProject, currentTask, currentAccountGroup, currentItem, ds, dsGL); if (periods == null) { return; } foreach (var hist in periods) { decimal amount = GetAmountFromPMHistory(ds, hist); lock (locker) { totalAmount += amount; } if (drilldown) { var key = new PMHistoryKeyTuple(currentProject.ContractID.Value, currentTask.TaskCD, currentAccountGroup.GroupID.Value, currentItem.InventoryID.Value); PXResult <PMHistory, PMProject, PMTask, PMAccountGroup, InventoryItem> drilldownRow = null; lock (drilldownData) { if (!drilldownData.TryGetValue(key, out drilldownRow)) { drilldownRow = new PXResult <PMHistory, PMProject, PMTask, PMAccountGroup, InventoryItem>(new PMHistory(), currentProject, currentTask, currentAccountGroup, currentItem); drilldownData.Add(key, drilldownRow); } } lock (drilldownRow) { AggregatePMHistoryForDrilldown(drilldownRow, hist); } } if (ds.Expand == ExpandType.AccountGroup) { lock (currentAccountGroup) { splitret[accountGroup][2] = (decimal)splitret[accountGroup][2] + amount; if (splitret[accountGroup][3] == null) { var dataSetCopy = new ARmDataSet(dataSet); dataSetCopy[PX.Objects.CS.RMReportReaderPM.Keys.StartAccountGroup] = dataSetCopy[PX.Objects.CS.RMReportReaderPM.Keys.EndAccountGroup] = currentAccountGroup.GroupCD; splitret[accountGroup][3] = dataSetCopy; } } } else if (ds.Expand == ExpandType.Project) { lock (currentProject) { splitret[project][2] = (decimal)splitret[project][2] + amount; if (splitret[project][3] == null) { var dataSetCopy = new ARmDataSet(dataSet); dataSetCopy[PX.Objects.CS.RMReportReaderPM.Keys.StartProject] = dataSetCopy[PX.Objects.CS.RMReportReaderPM.Keys.EndProject] = currentProject.ContractCD; splitret[project][3] = dataSetCopy; } } } else if (ds.Expand == ExpandType.ProjectTask) { lock (currentItem) { splitret[task][2] = (decimal)splitret[task][2] + amount; if (splitret[task][3] == null) { var dataSetCopy = new ARmDataSet(dataSet); dataSetCopy[PX.Objects.CS.RMReportReaderPM.Keys.StartProjectTask] = dataSetCopy[PX.Objects.CS.RMReportReaderPM.Keys.EndProjectTask] = currentTask.TaskCD; splitret[task][3] = dataSetCopy; } } } else if (ds.Expand == ExpandType.Inventory) { lock (currentItem) { splitret[item][2] = (decimal)splitret[item][2] + amount; if (splitret[item][3] == null) { var dataSetCopy = new ARmDataSet(dataSet); dataSetCopy[PX.Objects.CS.RMReportReaderPM.Keys.StartInventory] = dataSetCopy[PX.Objects.CS.RMReportReaderPM.Keys.EndInventory] = currentItem.InventoryCD; splitret[item][3] = dataSetCopy; } } } } }); }); }); }); if (drilldown) { var resultset = new PXResultset <PMHistory, PMProject, PMTask, PMAccountGroup, InventoryItem>(); foreach (var r in from row in drilldownData.Values let projectCD = ((PMProject)row[typeof(PMProject)]).With(_ => _.ContractCD) let taskCD = ((PMTask)row[typeof(Sub)]).With(_ => _.TaskCD) let accGroupCD = ((PMAccountGroup)row[typeof(PMAccountGroup)]).With(_ => _.GroupCD) let inventoryCD = ((InventoryItem)row[typeof(InventoryItem)]).With(_ => _.InventoryCD) orderby projectCD, taskCD, accGroupCD, inventoryCD select row) { resultset.Add(r); } return(resultset); } else if (ds.Expand != ExpandType.Nothing) { return(splitret); } else { return(totalAmount); } }
public virtual object GetHistoryValue(ARmDataSet dataSet, bool drilldown, Func <ARmDataSet, bool, object> del) { string rmType = Base.Report.Current.Type; if (rmType == ARmReport.PM) { RMDataSource ds = Base.DataSourceByID.Current; RMDataSourcePM dsPM = Base.Caches[typeof(RMDataSource)].GetExtension <RMDataSourcePM>(ds); ds.AmountType = (short?)dataSet[RMReportReaderGL.Keys.AmountType]; dsPM.StartAccountGroup = dataSet[Keys.StartAccountGroup] as string ?? ""; dsPM.EndAccountGroup = dataSet[Keys.EndAccountGroup] as string ?? ""; dsPM.StartProject = dataSet[Keys.StartProject] as string ?? ""; dsPM.EndProject = dataSet[Keys.EndProject] as string ?? ""; dsPM.StartProjectTask = dataSet[Keys.StartProjectTask] as string ?? ""; dsPM.EndProjectTask = dataSet[Keys.EndProjectTask] as string ?? ""; dsPM.StartInventory = dataSet[Keys.StartInventory] as string ?? ""; dsPM.EndInventory = dataSet[Keys.EndInventory] as string ?? ""; RMDataSourceGL dsGL = Base.Caches[typeof(RMDataSource)].GetExtension <RMDataSourceGL>(ds); dsGL.StartBranch = dataSet[RMReportReaderGL.Keys.StartBranch] as string ?? ""; dsGL.EndBranch = dataSet[RMReportReaderGL.Keys.EndBranch] as string ?? ""; dsGL.EndPeriod = ((dataSet[RMReportReaderGL.Keys.EndPeriod] as string ?? "").Length > 2 ? ((dataSet[RMReportReaderGL.Keys.EndPeriod] as string ?? "").Substring(2) + " ").Substring(0, 4) : " ") + ((dataSet[RMReportReaderGL.Keys.EndPeriod] as string ?? "").Length > 2 ? (dataSet[RMReportReaderGL.Keys.EndPeriod] as string ?? "").Substring(0, 2) : dataSet[RMReportReaderGL.Keys.EndPeriod] as string ?? ""); dsGL.EndPeriodOffset = (short?)(int?)dataSet[RMReportReaderGL.Keys.EndOffset]; dsGL.EndPeriodYearOffset = (short?)(int?)dataSet[RMReportReaderGL.Keys.EndYearOffset]; dsGL.StartPeriod = ((dataSet[RMReportReaderGL.Keys.StartPeriod] as string ?? "").Length > 2 ? ((dataSet[RMReportReaderGL.Keys.StartPeriod] as string ?? "").Substring(2) + " ").Substring(0, 4) : " ") + ((dataSet[RMReportReaderGL.Keys.StartPeriod] as string ?? "").Length > 2 ? (dataSet[RMReportReaderGL.Keys.StartPeriod] as string ?? "").Substring(0, 2) : dataSet[RMReportReaderGL.Keys.StartPeriod] as string ?? ""); dsGL.StartPeriodOffset = (short?)(int?)dataSet[RMReportReaderGL.Keys.StartOffset]; dsGL.StartPeriodYearOffset = (short?)(int?)dataSet[RMReportReaderGL.Keys.StartYearOffset]; List <object[]> splitret = null; if (ds.Expand != ExpandType.Nothing) { splitret = new List <object[]>(); } if (ds.AmountType == null || ds.AmountType == 0) { return(0m); } PMEnsureInitialized(); EnsureHistoryLoaded(dsPM); NormalizeDataSource(dsPM); List <PMAccountGroup> accountGroups = _accountGroupsRangeCache.GetItemsInRange(dataSet[Keys.StartAccountGroup] as string, group => group.GroupCD, (group, code) => group.GroupCD = code); List <PMProject> projects = _projectsRangeCache.GetItemsInRange(dataSet[Keys.StartProject] as string, project => project.ContractCD, (project, code) => project.ContractCD = code); List <PMTask> tasks = _tasksRangeCache.GetItemsInRange(dataSet[Keys.StartProjectTask] as string, task => task.TaskCD, (task, code) => task.TaskCD = code); List <InventoryItem> items = _itemRangeCache.GetItemsInRange(dataSet[Keys.StartInventory] as string, item => item.InventoryCD, (item, code) => item.InventoryCD = code); if (ds.Expand == ExpandType.AccountGroup) { accountGroups.ForEach(a => splitret.Add(new object[] { a.GroupCD, a.Description, 0m, null, string.Empty })); } else if (ds.Expand == ExpandType.Project) { projects.ForEach(p => splitret.Add(new object[] { p.ContractCD, p.Description, 0m, null, string.Empty })); } else if (ds.Expand == ExpandType.ProjectTask) { //To avoid useless expansion, first restrict list of tasks to those tasks which point to current projects tasks = tasks.Where(t => projects.Any(p => t.ProjectID == p.ContractID)).ToList <PMTask>(); tasks = tasks.GroupBy(t => t.TaskCD).Select(g => new PMTask() { TaskCD = g.Key, TaskID = g.Min(t => t.TaskID), Description = g.Min(t => t.Description) }).ToList <PMTask>(); tasks.ForEach(pt => splitret.Add(new object[] { pt.TaskCD, pt.Description, 0m, null, string.Empty })); } else if (ds.Expand == ExpandType.Inventory) { items.ForEach(i => splitret.Add(new object[] { i.InventoryCD, i.Descr, 0m, null, string.Empty })); } return(CalculateAndExpandValue(drilldown, ds, dsGL, dsPM, dataSet, accountGroups, projects, tasks, items, splitret)); } else { return(del(dataSet, drilldown)); } }