protected override EProcessState SetProcessState(POV pov, EProcessAction action, EProcessState targetState, string annotation, string[] paths, string[] files) { short newState = 0; if (HFM.HasVariableCustoms) { #if HFM_11_1_2_2 HFM.Try("Setting phased submission state for {0}", pov, () => _hsvProcessFlow.PhasedSubmissionProcessManagementChangeStateForMultipleEntities2ExtDim( pov.HfmSliceCOM, annotation, (int)action, false, false, (short)targetState, paths, files, out newState)); #else HFM.ThrowIncompatibleLibraryEx(); #endif } else { HFM.Try("Setting phased submission state for {0}", pov, () => _hsvProcessFlow.PhasedSubmissionProcessManagementChangeStateForMultipleEntities2( pov.Scenario.Id, pov.Year.Id, pov.Period.Id, new int[] { pov.Entity.Id }, new int[] { pov.Entity.ParentId }, pov.Value.Id, new int[] { pov.Account.Id }, new int[] { pov.ICP.Id }, new int[] { pov.Custom1.Id }, new int[] { pov.Custom2.Id }, new int[] { pov.Custom3.Id }, new int[] { pov.Custom4.Id }, annotation, (int)action, false, false, (short)targetState, paths, files, out newState)); } return((EProcessState)newState); }
protected override EProcessState SetProcessState(POV pu, EProcessAction action, EProcessState targetState, string annotation, string[] paths, string[] files) { short newState = 0; HFM.Try("Setting process unit state for {0}", pu, () => _hsvProcessFlow.ProcessManagementChangeStateForMultipleEntities2( pu.Scenario.Id, pu.Year.Id, pu.Period.Id, new int[] { pu.Entity.Id }, new int[] { pu.Entity.ParentId }, pu.Value.Id, annotation, (int)action, false, false, (short)targetState, paths, files, out newState)); return((EProcessState)newState); }
// To be able to change the status of a process unit, it needs to be: // unlocked, calculated, and valid protected bool CanAction(EProcessAction action, POV pu, bool consolidateIfNeeded, IOutput output) { bool ok = true; if (action == EProcessAction.Promote || action == EProcessAction.SignOff || action == EProcessAction.Submit || action == EProcessAction.Approve || action == EProcessAction.Publish) { ok = CheckCalcStatus(action, pu, consolidateIfNeeded, output); ok = ok && CheckValidationStatus(action, pu); } return(ok); }
// Check user has sufficient access rights for action protected bool HasSufficientAccess(EProcessAction action, POV pu, EAccessRights access, EProcessState state) { bool ok = false; switch (action) { case EProcessAction.Start: ok = access == EAccessRights.All; break; case EProcessAction.Promote: ok = access == EAccessRights.Promote || access == EAccessRights.All; break; case EProcessAction.Reject: ok = access == EAccessRights.All || ((access == EAccessRights.Read || access == EAccessRights.Promote) && state != EProcessState.Published); break; case EProcessAction.SignOff: ok = access == EAccessRights.Read || access == EAccessRights.Promote || access == EAccessRights.All; break; case EProcessAction.Submit: ok = access == EAccessRights.Promote || access == EAccessRights.All; break; case EProcessAction.Approve: ok = access == EAccessRights.Promote || access == EAccessRights.All; break; case EProcessAction.Publish: ok = access == EAccessRights.All; break; } if (ok) { _log.TraceFormat("User has sufficient privileges to {0} {1} {2}", action, ProcessUnitType, pu); } else { _log.WarnFormat("Insufficient privileges to {0} {1} {2}", action, ProcessUnitType, pu); } return(ok); }
/// Returns true if it is possible to go from start state to end state protected bool IsValidStateTransition(EProcessAction action, POV pu, EProcessState start, EProcessState end) { bool ok = false; switch (action) { case EProcessAction.Start: ok = start == EProcessState.NotStarted; break; case EProcessAction.Promote: ok = start >= EProcessState.FirstPass && start <EProcessState.ReviewLevel10 && end >= EProcessState.ReviewLevel1 && end <= EProcessState.ReviewLevel10 && end> start; break; case EProcessAction.Reject: ok = start != EProcessState.NotStarted; break; case EProcessAction.SignOff: ok = start >= EProcessState.ReviewLevel1; break; case EProcessAction.Submit: ok = start >= EProcessState.FirstPass && start < EProcessState.Submitted; break; case EProcessAction.Approve: ok = start == EProcessState.Submitted; break; case EProcessAction.Publish: ok = start >= EProcessState.Submitted && start < EProcessState.Published; break; } if (ok) { _log.TraceFormat("{0} {1} is in a valid state to {2}", ProcessUnitType.Capitalize(), pu, action); } else { _log.WarnFormat("{0} {1} is in the wrong state ({2}) to {3}", ProcessUnitType.Capitalize(), pu, start, action); } return(ok); }
protected bool CheckCalcStatus(EProcessAction action, POV pu, bool consolidateIfNeeded, IOutput output) { bool ok = false; var calcStatus = _session.Data.GetCalcStatus(pu); if (_log.IsDebugEnabled) { var cs = StringUtilities.Join(ECalcStatusExtensions.GetCellStatuses(calcStatus), ", "); _log.DebugFormat("Process unit calculation status for {0}: ({1})", pu, cs); } if (ECalcStatus.OK.IsSet(calcStatus) || ECalcStatus.OKButSystemChanged.IsSet(calcStatus) || ECalcStatus.NoData.IsSet(calcStatus)) { if (ECalcStatus.Locked.IsSet(calcStatus)) { _log.ErrorFormat("Cannot {0} {1} {2} as it has been locked", action, ProcessUnitType, pu); } else { _log.TraceFormat("Calculation status check passed for {0} of {1}", action, pu); ok = true; } } else if (consolidateIfNeeded) { if (ECalcStatus.NeedsCalculate.IsSet(calcStatus)) { _session.Calculate.CalculatePOV(pu, false); } else { _session.Calculate.ConsolidatePOV(pu, EConsolidationType.Impacted, output); } ok = true; } else { _log.ErrorFormat("Cannot {0} {1} {2} until it has been consolidated", action, ProcessUnitType, pu); } return(ok); }
protected bool CheckValidationStatus(EProcessAction action, POV pu) { bool ok = true; int group, phase; GetGroupPhase(pu, out group, out phase); if (phase == 0) { // Cell does not participate in process management throw new ArgumentException(string.Format("POV {0} is not valid for process management", pu)); } var account = _metadata.GetPhaseValidationAccount(phase); if (account.Id != Member.NOT_USED) { var pov = pu.Copy(); // Set validation account POV pov.Account = account; pov.View = _metadata.View.GetMember("<Scenario View>"); pov.ICP = _metadata.ICP.GetMember("[ICP Top]"); foreach (var id in _metadata.CustomDimIds) { pov[id] = account.GetTopCustomMember(id); } var valAmt = _session.Data.GetCellValue(pov); ok = valAmt == null || valAmt == 0; if (ok) { _log.TraceFormat("Validation status passed for {0}", pu); } else { _log.ErrorFormat("Cannot {0} {1} {2} until it passes validation", action, ProcessUnitType, pu); } } return(ok); }
/// Method to be implemented in sub-classes for setting the state of a /// single process unit represented by the POV. protected abstract EProcessState SetProcessState(POV processUnit, EProcessAction action, EProcessState targetState, string annotation, string[] paths, string[] files);
/// Method to be implemented in sub-classes for setting the state of /// process unit(s) represented by the ProcessUnits. protected void SetProcessState(ProcessUnits slice, EProcessAction action, ERole role, EProcessState targetState, string annotation, IEnumerable <string> documents, bool consolidateIfNeeded, IOutput output) { string[] paths = null, files = null; int processed = 0, skipped = 0, errored = 0, invalid = 0; EProcessState state; _security.CheckPermissionFor(ETask.ProcessManagement); if (role != ERole.Default) { _security.CheckRole(role); } // Convert document references if (documents != null) { var docs = documents.ToArray(); paths = new string[docs.Length]; files = new string[docs.Length]; for (int i = 0; i < docs.Length; ++i) { paths[i] = Path.GetDirectoryName(docs[i]); files[i] = Path.GetFileName(docs[i]); } } // Iterate over process units, performing action var PUs = GetProcessUnits(slice); output.InitProgress("Processing " + action.ToString(), PUs.Length); foreach (var pu in PUs) { var access = _security.GetProcessUnitAccessRights(pu, out state); if (state == targetState) { _log.FineFormat("{1} {2} is already at {2}", ProcessUnitType, pu, targetState); skipped++; } else if (IsValidStateTransition(action, pu, state, targetState) && HasSufficientAccess(action, pu, access, state) && CanAction(action, pu, consolidateIfNeeded, output)) { try { SetProcessState(pu, action, targetState, annotation, paths, files); processed++; } catch (HFMException ex) { _log.Error(string.Format("Unable to {0} {1} {2}", action, ProcessUnitType, pu), ex); errored++; } } else { invalid++; } if (output.IterationComplete()) { break; } } output.EndProgress(); _log.InfoFormat("Results for {0} of {1} {2}s: {3} successful, {4} skipped, {5} errored, {6} invalid", action, PUs.Length, ProcessUnitType, processed, skipped, errored, invalid); if (errored > 0) { throw new Exception(string.Format("Failed to {0} {1} {2}s", action, errored, ProcessUnitType)); } }