/// <summary> /// Moves instance's process to nextElement id. Returns the instance together with process events. /// </summary> public ProcessStateChange ProcessNext(Instance instance, string nextElementId, ClaimsPrincipal userContext) { if (instance.Process != null) { try { string validNextEmentId = CheckNextElementId(instance, nextElementId); ProcessStateChange result = new ProcessStateChange { OldProcessState = new ProcessState() { Started = instance.Process.Started, CurrentTask = instance.Process.CurrentTask, StartEvent = instance.Process.StartEvent } }; result.Events = MoveProcessToNext(instance, validNextEmentId, userContext); result.NewProcessState = instance.Process; return(result); } catch { _logger.LogError($"Unable to get next for {instance.Id}"); } } return(null); }
private void ProcessStateChangeHandler(ProcessStateChange obj) { try { var processChange = obj.Change; var name = obj.Name; var process = obj.Process; switch (processChange) { case ProcessChange.Started: if (_config.Kernel.Contains(name)) { ConfigProcess(process); Kernel += process; } if (_config.Client.Contains(name)) { ConfigProcess(process); Client += process; } break; case ProcessChange.Stopped: if (_config.Kernel.Contains(name)) { Kernel += null !; } if (_config.Client.Contains(name)) { Client += null !; } break; default: throw new ArgumentOutOfRangeException(); } if (Kernel != null && Client != null) { Status += Context.Loc().RequestString("uistatusstartet"); } if (Kernel == null && Client == null) { Status += Context.Loc().RequestString("uistatusstopped"); } } catch (Exception e) { Status += "Fehler: " + e.Message; } }
/// <summary> /// Start process start and goto next. Returns /// </summary> public ProcessStateChange ProcessStartAndGotoNextTask(Instance instance, string proposedStartEvent, ClaimsPrincipal user) { _logger.LogInformation($"ProcessStartAndGotoNextTask for {instance.Id}"); // start process ProcessStateChange startChange = ProcessStart(instance, proposedStartEvent, user); string nextValidElement = GetNextElement(instance.Process.StartEvent); // move next ProcessStateChange nextChange = ProcessNext(instance, nextValidElement, user); // consolidate events startChange.Events.AddRange(nextChange.Events); startChange.NewProcessState = nextChange.NewProcessState; return(startChange); }
public async Task <ActionResult <ProcessState> > StartProcess( [FromRoute] string org, [FromRoute] string app, [FromRoute] int instanceOwnerPartyId, [FromRoute] Guid instanceGuid, [FromQuery] string startEvent = null) { Instance instance = null; try { instance = await _instanceService.GetInstance(app, org, instanceOwnerPartyId, instanceGuid); if (instance.Process != null) { return(Conflict($"Process is already started. Use next.")); } string validStartElement = processHelper.GetValidStartEventOrError(startEvent, out ProcessError startEventError); if (startEventError != null) { return(Conflict(startEventError.Text)); } // trigger start event and goto next task ProcessStateChange processStateChange = _processService.ProcessStartAndGotoNextTask(instance, validStartElement, User); Instance updatedInstance = await UpdateInstanceAndDispatchEvents(instance, processStateChange); return(Ok(updatedInstance.Process)); } catch (PlatformHttpException e) { return(HandlePlatformHttpException(e, $"Unable to start the process for instance {instance.Id} of {instance.AppId}")); } catch (Exception startException) { _logger.LogError($"Unable to start the process for instance {instance.Id} of {instance.AppId}. Due to {startException}"); return(ExceptionResponse(startException, $"Unable to start the process for instance {instance.Id} of {instance.AppId}")); } }
/// <summary> /// Start process start and goto next. Returns /// </summary> public ProcessStateChange ProcessStartAndGotoNextTask(Instance instance, string proposedStartEvent, ClaimsPrincipal user) { _logger.LogInformation($"ProcessStartAndGotoNextTask for {instance.Id}"); // start process ProcessStateChange startChange = ProcessStart(instance, proposedStartEvent, user); InstanceEvent startEvent = CopyInstanceEventValue(startChange.Events.First()); // move next string nextValidElement = GetNextElement(instance.Process.StartEvent); ProcessStateChange nextChange = ProcessNext(instance, nextValidElement, user); InstanceEvent goToNextEvent = CopyInstanceEventValue(nextChange.Events.First()); ProcessStateChange processStateChange = new ProcessStateChange { OldProcessState = startChange.OldProcessState, NewProcessState = nextChange.NewProcessState, Events = new List <InstanceEvent> { startEvent, goToNextEvent } }; return(processStateChange); }
public async Task <ActionResult <ProcessState> > CompleteProcess( [FromRoute] string org, [FromRoute] string app, [FromRoute] int instanceOwnerPartyId, [FromRoute] Guid instanceGuid) { Instance instance = null; try { instance = await _instanceService.GetInstance(app, org, instanceOwnerPartyId, instanceGuid); } catch (PlatformHttpException e) { return(HandlePlatformHttpException(e, "Could not complete process.")); } if (instance.Process == null) { return(Conflict($"Process is not started. Use start!")); } else { if (instance.Process.Ended.HasValue) { return(Conflict($"Process is ended. It cannot be restarted.")); } } string currentTaskId = instance.Process.CurrentTask?.ElementId ?? instance.Process.StartEvent; if (currentTaskId == null) { return(Conflict($"Instance does not have valid currentTask")); } // do next until end event is reached or task cannot be completed. int counter = 0; do { string altinnTaskType = instance.Process.CurrentTask?.AltinnTaskType; bool authorized = await AuthorizeAction(altinnTaskType, org, app, instanceOwnerPartyId, instanceGuid); if (!authorized) { return(Forbid()); } if (!await CanTaskBeEnded(instance, currentTaskId)) { return(Conflict($"Instance is not valid for task {currentTaskId}. Automatic completion of process is stopped")); } List <string> nextElements = processHelper.Process.NextElements(currentTaskId); if (nextElements.Count > 1) { return(Conflict($"Cannot complete process. Multiple outgoing sequence flows detected from task {currentTaskId}. Please select manually among {nextElements}")); } string nextElement = nextElements.First(); try { ProcessStateChange nextResult = _processService.ProcessNext(instance, nextElement, User); if (nextResult != null) { instance = await UpdateInstanceAndDispatchEvents(instance, nextResult); currentTaskId = instance.Process.CurrentTask?.ElementId; } else { return(Conflict($"Cannot complete process. Unable to move to next element {nextElement}")); } } catch (Exception ex) { return(ExceptionResponse(ex, "Complete process failed.")); } counter++; }while (instance.Process.EndEvent == null || counter > MAX_ITERATIONS_ALLOWED); if (counter > MAX_ITERATIONS_ALLOWED) { _logger.LogError($"More than {counter} iterations detected in process. Possible loop. Fix app {org}/{app}'s process definition!"); return(StatusCode(500, $"More than {counter} iterations detected in process. Possible loop. Fix app process definition!")); } return(Ok(instance.Process)); }
public async Task <ActionResult <ProcessState> > NextElement( [FromRoute] string org, [FromRoute] string app, [FromRoute] int instanceOwnerPartyId, [FromRoute] Guid instanceGuid, [FromQuery] string elementId = null) { try { Instance instance = await _instanceService.GetInstance(app, org, instanceOwnerPartyId, instanceGuid); if (instance.Process == null) { return(Conflict($"Process is not started. Use start!")); } if (instance.Process.Ended.HasValue) { return(Conflict($"Process is ended.")); } if (!string.IsNullOrEmpty(elementId)) { ElementInfo elemInfo = processHelper.Process.GetElementInfo(elementId); if (elemInfo == null) { return(BadRequest($"Requested element id {elementId} is not found in process definition")); } } string altinnTaskType = instance.Process.CurrentTask?.AltinnTaskType; if (altinnTaskType == null) { return(Conflict($"Instance does not have current altinn task type information!")); } bool authorized = await AuthorizeAction(altinnTaskType, org, app, instanceOwnerPartyId, instanceGuid); if (!authorized) { return(Forbid()); } string currentElementId = instance.Process.CurrentTask?.ElementId; if (currentElementId == null) { return(Conflict($"Instance does not have current task information!")); } if (currentElementId.Equals(elementId)) { return(Conflict($"Requested process element {elementId} is same as instance's current task. Cannot change process.")); } string nextElement = processHelper.GetValidNextElementOrError(currentElementId, elementId, out ProcessError nextElementError); if (nextElementError != null) { return(Conflict(nextElementError.Text)); } if (await CanTaskBeEnded(instance, currentElementId)) { ProcessStateChange nextResult = _processService.ProcessNext(instance, nextElement, User); if (nextResult != null) { Instance changedInstance = await UpdateInstanceAndDispatchEvents(instance, nextResult); return(Ok(changedInstance.Process)); } } return(Conflict($"Cannot complete/close current task {currentElementId}. The data element(s) assigned to the task are not valid!")); } catch (PlatformHttpException e) { return(HandlePlatformHttpException(e, "Process next failed.")); } catch (Exception exception) { return(ExceptionResponse(exception, "Process next failed.")); } }
private async Task <Instance> UpdateInstanceAndDispatchEvents(Instance instance, ProcessStateChange processStateChange) { await NotifyAppAboutEvents(_altinnApp, instance, processStateChange.Events); // need to update the instance process and then the instance in case appbase has changed it, e.g. endEvent sets status.archived Instance instanceWithUpdatedProcess = await _instanceService.UpdateProcess(instance); Instance updatedInstance = await _instanceService.UpdateInstance(instanceWithUpdatedProcess); await _processService.DispatchProcessEventsToStorage(updatedInstance, processStateChange.Events); // remember to get the instance anew since AppBase can have updated a data element or stored something in the database. updatedInstance = await _instanceService.GetInstance(updatedInstance); return(updatedInstance); }