void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var haveStarted = GetArgumentKey("forEachHaveStarted"); var foreachList = GetArgumentKey("forEachResourceList"); var resourceListKey = GetArgumentKey("foreachList"); var selectedResourceKey = GetArgumentKey("foreachSelectedResource"); IEnumerable <IEntity> resourceList; if (!(context.GetArgValue <bool?>(ActivityInstance, haveStarted) ?? false)) { context.SetArgValue(ActivityInstance, haveStarted, true); // // it's the first time into the loop // object listObj; if (inputs.TryGetValue(resourceListKey, out listObj)) { if (listObj == null) { throw new ApplicationException("The [List] argument is null. This should never happen."); } resourceList = (IEnumerable <IEntity>)listObj; } else { throw new ApplicationException("The [List] is missing from the input arguments. This should never happen."); } } else { resourceList = context.GetArgValue <IEnumerable <IEntity> >(ActivityInstance, foreachList); } var selectedResourceRef = resourceList.FirstOrDefault(); if (selectedResourceRef != null) { context.SetArgValue(ActivityInstance, selectedResourceKey, selectedResourceRef); resourceList = resourceList.Skip(1); context.SetArgValue(ActivityInstance, foreachList, resourceList); context.ExitPointId = Entity.GetId(LoopExitPointAlias); } else { // We have finished context.SetArgValue(ActivityInstance, haveStarted, false); context.SetArgValue(ActivityInstance, foreachList, null); context.ExitPointId = Entity.GetId("core", "foreachCompletedExitPoint"); } }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var ResourceTypeToCreateKey = GetArgumentKey("createActivityResourceArgument"); var CreatedResourceKey = GetArgumentKey("createActivityCreatedResource"); IEntity newEntity = null; var resTypeRef = (IEntity)inputs[ResourceTypeToCreateKey]; var resType = resTypeRef?.As <EntityType>(); if (resType == null) { throw new WorkflowRunException_Internal("Input resource argument must be a type.", null); } var activityAs = ActivityInstance.Cast <EntityWithArgsAndExits>(); Action <IEntity> updateAction = (e) => UpdateArgsHelper.UpdateEntityFromArgs(activityAs, inputs, e); DatabaseContext.RunWithRetry(() => { newEntity = PerformCreate(resType, updateAction); }); context.SetArgValue(ActivityInstance, CreatedResourceKey, newEntity); }
/// <summary> /// Handles the response that was received from a request this activity made. /// </summary> /// <param name="context">The workflow run context.</param> /// <param name="request">The original request object.</param> /// <param name="response">The object that was received in response to the request.</param> protected override void OnResponse(IRunState context, TenantOperationRequest request, TenantInfoResponse response) { if (response == null) { throw new ArgumentNullException("response"); } var databaseId = request.DatabaseId; if (string.IsNullOrEmpty(databaseId)) { throw new WorkflowRunException("The platform context for this tenant was unknown."); } var tenantInfo = response.Tenants.FirstOrDefault(); if (tenantInfo == null) { throw new WorkflowRunException("No information about the tenant was received."); } var tenant = PlatformService.CreateOrUpdateTenant(databaseId, tenantInfo); if (tenant == null) { throw new WorkflowRunException("Failed to create or update this tenant entity."); } var tenantKey = GetArgumentKey(TenantArgumentAlias); context.SetArgValue(ActivityInstance, tenantKey, tenant); }
/// <summary> /// Continue a paused activity /// </summary> /// <returns>True if the activity has completed, false if it is paused.</returns> public override bool OnResume(IRunState context, IWorkflowEvent resumeEvent) { var userCompletesEvent = resumeEvent as PromptUserTaskCompletedEvent; if (userCompletesEvent != null) { context.ExitPointId = new EntityRef("promptUserCompleted"); var userTaskId = userCompletesEvent.UserTaskId; var userTask = Entity.Get <PromptUserTask>(userTaskId, PromptUserTask.PromptForTaskStateInfo_Field); if (userTask != null) { // load the state information in the task back into the workflow run context foreach (var arg in userTask.PromptForTaskArguments) { var input = userTask.PromptForTaskStateInfo.FirstOrDefault(si => si.StateInfoArgument.Id == arg.ActivityPromptArgument.Id); if (input == null) { continue; } context.SetArgValue(input.StateInfoArgument, ActivityArgumentHelper.GetArgParameterValue(input.StateInfoValue)); } Entity.Delete(userTask); } } return(true); }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var resource = GetArgumentEntity <Resource>(inputs, "core:createLinkResourceArgument"); if (resource == null) { throw new WorkflowRunException("The 'Resource' argument is empty. It must have a value."); } string Url = NavigationHelper.GetResourceViewUrl(resource.Id).ToString(); string anchor = string.Format("<a href='{0}'>{1}</a>", Url, XmlHelper.EscapeXmlText(resource.Name ?? "[Unnamed]")); context.SetArgValue(ActivityInstance, GetArgumentKey("core:createLinkUrlOutput"), Url); context.SetArgValue(ActivityInstance, GetArgumentKey("core:createLinkAnchorOutput"), anchor); }
/// <summary> /// Handles the response that was received from a request this activity made. /// </summary> /// <param name="context">The workflow run context.</param> /// <param name="request">The original request object.</param> /// <param name="response">The object that was received in response to the request.</param> protected override void OnResponse(IRunState context, ApplicationOperationRequest request, ApplicationInfoResponse response) { if (response == null) { throw new ArgumentNullException("response"); } var databaseId = request.DatabaseId; if (string.IsNullOrEmpty(databaseId)) { throw new WorkflowRunException("The platform context for this user was unknown."); } var tenant = PlatformService.UpdateInstalledApplications(databaseId, request.Tenant, response.Installed); if (tenant == null) { throw new WorkflowRunException("Cannot update the tenant with apps installed."); } var installedKey = GetArgumentKey(ApplicationsInstalledArgumentAlias); context.SetArgValue(ActivityInstance, installedKey, tenant.HasAppsInstalled.ToList()); }
void ProcessResult(IRunState context, WorkflowRun run) { if (run.WorkflowRunStatus_Enum != WorkflowRunState_Enumeration.WorkflowRunCompleted) { throw new InnerWorkflowFailedException(string.Format("Inner workflow '{0}' failed", run.WorkflowBeingRun.Name)); } var proxyExitPoint = run.GetExitPoint(); var matchingExitPoint = context.Metadata.GetExitpointsForActivity(ActivityInstance.Id).SingleOrDefault(ep => ep.Name == proxyExitPoint.Name); if (matchingExitPoint == null) { throw new WorkflowRunException("Workflow proxy returned using an exit point that doesn't match anything in the parent"); } context.ExitPointId = matchingExitPoint; var outputs = run.GetOutput(); var outArgs = ActivityInstance.GetOutputArguments(); // copy the values from the results into the arguments witht eh same name foreach (var arg in outArgs) { var name = arg.Name; object value = null; if (outputs.TryGetValue(name, out value)) { context.SetArgValue(ActivityInstance, arg, value); } } }
/// <summary> /// Runs when the activity is run by the workflow. /// </summary> /// <param name="context">The run state.</param> /// <param name="inputs">The inputs.</param> void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { using (Profiler.Measure("ExportToImplementation.OnRunNow")) { var name = GetArgumentValue <string>(inputs, "inExportToName"); var report = GetArgumentEntity <Report>(inputs, "inExportToReport"); var format = GetArgumentEntity <ExportFileTypeEnum>(inputs, "inExportToFormat"); if (String.IsNullOrWhiteSpace(name)) { name = GenerateName(report.Name); } var description = string.Format(DescriptionFormat, report.Name ?? "[Unnamed]", DateTime.Now.ToShortTimeString()); Document generatedDoc; using (CustomContext.SetContext(context.EffectiveSecurityContext)) { var timeZone = RequestContext.GetContext().TimeZone ?? TimeZoneHelper.SydneyTimeZoneName; generatedDoc = ExportTo(report, name, description, timeZone, ToExportFormat(format)); } context.SetArgValue(ActivityInstance, GetArgumentKey("core:outExportToDoc"), generatedDoc); } }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { _activityInputs = inputs; try { if (string.IsNullOrEmpty(TenantEmailSetting.SmtpServer)) { throw new Exception("smtpServer has not been specified."); } var sendEmailRecipientsType = GetArgumentValue <Resource>(inputs, "core:sendEmailRecipientsType"); var sentEmailMessages = new List <SentEmailMessage>(); if (string.IsNullOrEmpty(sendEmailRecipientsType?.Alias) || (sendEmailRecipientsType?.Alias == "core:sendEmailActivityRecipientsAddress")) { sentEmailMessages.Add(GenerateEmailToRecipientsExpression()); } else { var sendEmailDistributionType = GetArgumentValue <Resource>(inputs, "core:sendEmailDistributionType"); if (string.IsNullOrEmpty(sendEmailDistributionType?.Alias) || (sendEmailDistributionType?.Alias == "core:sendEmailActivityGroupDistribution")) { sentEmailMessages.Add(GenerateGroupEmailsToRecipientsList()); } else { sentEmailMessages.AddRange(GenerateIndividualEmailsToRecipientsList()); } } var mailMessages = new List <MailMessage>(); sentEmailMessages.RemoveAll(msg => string.IsNullOrEmpty(msg.EmTo) && string.IsNullOrEmpty(msg.EmCC) && string.IsNullOrEmpty(msg.EmBCC)); sentEmailMessages.RemoveAll(msg => string.IsNullOrEmpty(msg.EmSubject)); sentEmailMessages.ForEach(msg => { msg.EmSentDate = DateTime.UtcNow; msg.Save(); mailMessages.Add(msg.ToMailMessage()); }); RecordInfoToUserLog(context, $"Sending {sentEmailMessages.Count} emails"); if (sentEmailMessages.Count == 0) { context.ExitPointId = Entity.GetId("core:sendEmailSucceededSend"); return; } EmailSender.SendMessages(mailMessages); context.SetArgValue(ActivityInstance, GetArgumentKey("core:outSentEmailMessages"), sentEmailMessages); context.ExitPointId = Entity.GetId("core:sendEmailSucceededSend"); } catch (Exception ex) { RecordErrorToUserLog(context, ex); context.ExitPointId = Entity.GetId("core:sendEmailFailedSend"); } }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var activityAs = ActivityInstance.Cast <AssignToVariable>(); var valueArgument = Entity.Get <ActivityArgument>("assignValueArgument", Resource.Name_Field); var targetVar = activityAs.TargetVariable; context.SetArgValue(targetVar, inputs[valueArgument]); }
void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { var typeRefKey = GetArgumentKey("getResourcesResourceType"); var reportRefKey = GetArgumentKey("getResourcesReport"); var listKey = GetArgumentKey("getResourcesList"); var firstKey = GetArgumentKey("getResourcesFirst"); var countKey = GetArgumentKey("getResourcesCount"); object o; EntityType resourceType = null; IEntity reportRef = null; if (inputs.TryGetValue(typeRefKey, out o)) { if (o != null) { resourceType = ((IEntity)o).As <EntityType>(); } } if (inputs.TryGetValue(reportRefKey, out o)) { if (o != null) { reportRef = (IEntity)o; } } if (resourceType == null && reportRef == null) { throw new WorkflowRunException("Get Resources must have one of either the Type or Report parameters specified."); } IEnumerable <IEntity> list = null; SecurityBypassContext.RunAsUser(() => { list = reportRef != null ? GetListFromReport(context, reportRef) : GetListFromType(resourceType); }); context.SetArgValue(ActivityInstance, listKey, list); context.SetArgValue(ActivityInstance, firstKey, list.FirstOrDefault()); context.SetArgValue(ActivityInstance, countKey, list.Count()); }
public override bool OnResume(IRunState context, IWorkflowEvent resumeEvent) { var userTaskEntity = context.GetArgValue <IEntity>(ActivityInstance, GetArgumentKey("core:outDisplayFormUserTask")); var keepHistory = context.GetArgValue <bool>(ActivityInstance, GetArgumentKey("core:dfaInternalKeepHistory")); var userTask = userTaskEntity != null?userTaskEntity.As <DisplayFormUserTask>() : null; // We could have a combination of a deleted user task and a time-out if (!HandleTimeout(context, resumeEvent)) // handle timeout will set the exit point { HandleResumeTransition(context, (IWorkflowUserTransitionEvent)resumeEvent); if (!(userTask.HideComment ?? false)) { context.SetArgValue(ActivityInstance, GetArgumentKey("core:outTaskComment"), userTask.TaskComment); } if (keepHistory) { var writableTask = userTask.AsWritable <DisplayFormUserTask>(); writableTask.TaskStatus_Enum = TaskStatusEnum_Enumeration.TaskStatusCompleted; writableTask.Save(); } } if (userTask != null) { if (keepHistory) { if (userTask.LogEntryForUserAction != null) { UpdateLogEntry(userTask); } } else { context.SetArgValue(ActivityInstance, GetArgumentKey("core:outDisplayFormUserTask"), null); Entity.Delete(userTask); } } return(true); }
//private const string ClonedNameFormat = "{0} (clone)"; void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { using (Profiler.MeasureAndSuppress("CloneImplementation.OnRunNow")) { var resourceKey = GetArgumentKey("resourceToCloneArgument"); var definitionKey = GetArgumentKey("newDefinitionCloneArgument"); var clonedKey = GetArgumentKey("clonedResourceArgument"); var resId = (IEntity)inputs[resourceKey]; var resource = resId.As <Resource>(); IEntity clone = null; EntityType cloneType = null; object definitionObj; if (inputs.TryGetValue(definitionKey, out definitionObj)) { if (definitionObj != null) { cloneType = ((IEntity)definitionObj).As <EntityType>(); } } try { using (CustomContext.SetContext(context.EffectiveSecurityContext)) { using (var ctx = DatabaseContext.GetContext(true)) { var activityAs = ActivityInstance.Cast <EntityWithArgsAndExits>(); Action <IEntity> updateAction = c => UpdateArgsHelper.UpdateEntityFromArgs(activityAs, inputs, c); clone = CreateClone(resource, cloneType, updateAction); clone.Save(); ctx.CommitTransaction(); } }; } catch (DuplicateKeyException ex) { throw new WorkflowRunException("The Clone item failed during saving: " + ex.Message, ex); } catch (ValidationException ex) { throw new WorkflowRunException("The Cloned item failed validation during saving: " + ex.Message, ex); } context.SetArgValue(ActivityInstance, clonedKey, clone); } }
/// <summary> /// Update any arguments on the workflow with the resolved expressions /// </summary> private void UpdateWorkflowArguments(IRunState context, Dictionary <WfExpression, object> resolvedExpressions) { foreach (var kvp in resolvedExpressions) { var expression = kvp.Key; ActivityArgument arg = context.Metadata.GetArgumentPopulatedByExpression(expression); context.SetArgValue(arg, kvp.Value); } }
/// <summary> /// Runs the activity. /// </summary> /// <param name="context">The run context.</param> /// <param name="inputs">The input parameters.</param> public void OnRunNow(IRunState context, ActivityInputs inputs) { var campaign = GetArgumentEntity <SurveyCampaign>(inputs, "inStartSurveyCampaign"); var tasks = campaign.Launch().ToList(); Entity.Save(tasks); var responses = tasks.Select(t => t.UserSurveyTaskSurveyResponse); context.SetArgValue(ActivityInstance, GetArgumentKey("core:outStartSurveyResponses"), responses); }
/// <summary> /// Start the activity running /// </summary> /// <returns>True if the activity has completed, false if it is paused. Along with a sequence number of if it is paused</returns> public override bool OnStart(IRunState context, ActivityInputs inputs) { var survey = GetArgumentEntity <UserSurvey>(inputs, "inLaunchPersonSurvey"); var recipients = GetArgumentEntityList <Person>(inputs, "inLaunchPersonRecipients").ToList(); var targetObject = GetArgumentEntity <UserResource>(inputs, "inLaunchPersonTarget"); var taskName = GetArgumentValue <string>(inputs, "inLaunchPersonTaskName"); var dueInDays = GetArgumentValue(inputs, "inLaunchPersonDueDays", 0m); var pause = GetArgumentValue(inputs, "inLaunchPersonPause", false); // ensure that there is at least one recipient if (recipients.Count <= 0) { throw new WorkflowRunException("The recipients list for the Survey was empty."); } var campaign = Entity.Create <SurveyPersonCampaign>(); campaign.Name = $"Person Campaign ({survey.Name})"; campaign.SurveyForCampaign = survey; campaign.CampaignPersonRecipients.AddRange(recipients); if (dueInDays > 0) { campaign.SurveyClosesOn = DateTime.UtcNow.AddDays(decimal.ToDouble(dueInDays)); } var tasks = campaign.Launch(campaign.SurveyClosesOn, targetObject, taskName).ToList(); if (pause) { foreach (var task in tasks) { // this will do the save for us. context.SetUserTask(task.Cast <BaseUserTask>()); } } else { Entity.Save(tasks); } var responses = tasks.Select(t => t.UserSurveyTaskSurveyResponse); context.SetArgValue(ActivityInstance, GetArgumentKey("core:outLaunchPersonResponses"), responses); // Deal with time-outs. Time-outs can only occur if there is due date and we are pausing. if (pause) { SetTimeoutIfNeeded(context, dueInDays); } // Note that there is no need to set an exit point if we are not pausing as the default exit point will be used. return(!pause); }
/// <summary> /// Copy any input arguments /// </summary> public void MapInitialInput(IRunState context, IDictionary <ActivityArgument, object> inputArguments) { foreach (var kvp in inputArguments) { context.SetArgValue(kvp.Key, kvp.Value); } // Do the initial variable initialization var variableExpressions = _activityInstanceAsWf.Variables.Select(v => v.PopulatedByExpression.FirstOrDefault()).Where(e => e != null).ToList(); var resolvedExpressions = ResolveExpressions(context, variableExpressions); UpdateWorkflowArguments(context, resolvedExpressions); }
/// <summary> /// Handles the response that was received from a request this activity made. /// </summary> /// <param name="context">The workflow run context.</param> /// <param name="request">The original request object.</param> /// <param name="response">The object that was received in response to the request.</param> protected override void OnResponse(IRunState context, LogRequest request, LogResponse response) { if (response == null) { throw new ArgumentNullException("response"); } if (response.Time == DateTime.MinValue) { throw new ArgumentException("response.time value was not set."); } var logTimeKey = GetArgumentKey(LogTimeArgumentAlias); context.SetArgValue(ActivityInstance, logTimeKey, response.Time.ToLocalTime()); }
private const decimal DefaultTimeOutMins = 0; // no time out public override bool OnStart(IRunState context, ActivityInputs inputs) { var users = GetArgumentEntityList(inputs, "inPeople"); var message = GetArgumentValue <String>(inputs, "inMessage"); var waitForReplies = GetArgumentValueStruct <bool>(inputs, "inWaitForReplies"); var timeoutDays = GetArgumentValue <decimal>(inputs, "inNotifyTimeOut", 0); var acceptRepliesDays = GetArgumentValue <decimal>(inputs, "inAcceptRepliesFor", 1); var linkToRecord = GetArgumentEntity <UserResource>(inputs, "inLinkToRecord"); if (!Factory.Current.Resolve <INotifier>().IsConfigured) { throw new WorkflowRunException("No tenant notifier has been configured in tenant general settings."); } // // Notification needs to be created first to ensure that a fast response will not be processed before the notification is created // var effectiveUser = Entity.Get <UserAccount>(context.EffectiveSecurityContext.Identity.Id); var notification = Entity.Create <Notification>(); notification.NMessage = message; notification.SecurityOwner = effectiveUser; // The workflow runner can delete and update the notification and the send and replies. notification.NRelatedRecord = linkToRecord; notification.NAcceptRepliesUntil = DateTime.UtcNow.AddDays(Convert.ToDouble(acceptRepliesDays)); CopyReplyMap(context, notification); notification.Save(); context.SetArgValue(ActivityInstance, GetArgumentKey("core:outNotificationRecord"), notification); if (waitForReplies) { SetTimeoutIfNeeded(context, timeoutDays); // Note that there is no timeout exit. } SendMessagesInBackground(context, notification.Id, users.Select(u => u.Id).ToList(), waitForReplies); return(false); }
/// <summary> /// Runs when the activity is run by the workflow. /// </summary> /// <param name="context">The run state.</param> /// <param name="inputs">The inputs.</param> void IRunNowActivity.OnRunNow(IRunState context, ActivityInputs inputs) { using (Profiler.Measure("GenerateDocImplementation.OnRunNow")) { var inGenerateDocTemplateKey = GetArgumentKey("inGenerateDocTemplate"); var inGenerateDocNameKey = GetArgumentKey("inGenerateDocName"); var inGenerateDocSourceKey = GetArgumentKey("inGenerateDocSource"); var reportTemplate = ((IEntity)inputs[inGenerateDocTemplateKey]).As <ReportTemplate>(); var name = inputs.ContainsKey(inGenerateDocNameKey) ? (string)inputs[inGenerateDocNameKey] : null; if (String.IsNullOrWhiteSpace(name)) { name = GenerateName(reportTemplate.Name); } var description = string.Format(DescriptionFormat, reportTemplate.Name ?? "[Unnamed]", DateTime.Now.ToShortTimeString()); var sourceResource = inputs.ContainsKey(inGenerateDocSourceKey) ? ((IEntity)inputs[inGenerateDocSourceKey]) : null; Document generatedDoc; using (CustomContext.SetContext(context.EffectiveSecurityContext)) { var timeZone = RequestContext.GetContext().TimeZone ?? TimeZoneHelper.SydneyTimeZoneName; var templateFile = reportTemplate.ReportTemplateUsesDocument; try { generatedDoc = GenerateDoc(templateFile, sourceResource, name, description, timeZone); } catch (DocGenException ex) { throw new WorkflowRunException(ex.Message); } } context.SetArgValue(ActivityInstance, GetArgumentKey("core:outGenerateDocDoc"), generatedDoc); } }
/// <summary> /// Start the activity running /// </summary> /// <returns>True if the activity has completed, false if it is paused. Along with a sequence number of if it is paused</returns> public override bool OnStart(IRunState context, ActivityInputs inputs) { var targets = GetArgumentEntityList <UserResource>(inputs, "inLaunchTargetTargets").ToList(); var survey = GetArgumentEntity <UserSurvey>(inputs, "inLaunchTargetSurvey"); var surveyTaker = GetArgumentEntity <Relationship>(inputs, "inLaunchTargetSurveyTaker"); var targetDefinition = GetArgumentEntity <Definition>(inputs, "inLaunchTargetTargetObject"); var taskName = GetArgumentValue <string>(inputs, "inLaunchTargetTaskName"); var dueInDays = GetArgumentValue(inputs, "inLaunchTargetDueDays", 0m); var pause = GetArgumentValue(inputs, "inLaunchTargetPause", false); EntityType targetType; DirectionEnum_Enumeration targetDirection; // ensure that there is at least one target if (targets.Count <= 0) { throw new WorkflowRunException("The targets list for the Survey was empty."); } // ensure the relationship is valid (as there is no UI validation in workflow) var surveyTakerAttachesToPerson = surveyTaker.ToType.GetAncestorsAndSelf().Select(t => t.Id).Contains(Person.Person_Type.Id) || surveyTaker.FromType.GetAncestorsAndSelf().Select(t => t.Id).Contains(Person.Person_Type.Id); if (!surveyTakerAttachesToPerson) { throw new WorkflowRunException("Invalid relationship used for Survey taker. Must connect to Person."); } // Derive the direction and (base-most) target type for this campaign, based on the relationship that has been input if (surveyTaker.ToType .GetAncestorsAndSelf().Select(t => t.Id) .Contains(Person.Person_Type.Id)) { targetType = surveyTaker.FromType; targetDirection = DirectionEnum_Enumeration.Forward; } else { targetType = surveyTaker.ToType; targetDirection = DirectionEnum_Enumeration.Reverse; } // If a target object definition has been specified, then enforce it if (targetDefinition != null) { // override the target type derived above targetType = targetDefinition.As <EntityType>(); // all the inputs we have should be of this type var targetsConform = targets.All(target => { return(target.GetAllTypes().Select(t => t.Id).Contains(targetType.Id)); }); if (!targetsConform) { throw new WorkflowRunException("All targets must conform to the Target object if it has been specified."); } // validate that the relationship also connects to the target object type var relTypeToCheck = targetDirection == DirectionEnum_Enumeration.Forward ? surveyTaker.FromType : surveyTaker.ToType; var surveyTakerAttachesToTargetObject = targetType.GetAncestorsAndSelf().Select(t => t.Id).Contains(relTypeToCheck.Id); if (!surveyTakerAttachesToTargetObject) { throw new WorkflowRunException("Invalid relationship used for Survey taker. Must connect to the Target object if it has been specified."); } } var campaign = Entity.Create <SurveyTargetCampaign>(); campaign.Name = $"Target Campaign ({survey.Name})"; campaign.SurveyForCampaign = survey; campaign.CampaignTarget = targetType.As <Definition>(); campaign.CampaignTargetRelationship = surveyTaker; campaign.CampaignTargetRelationshipDirection_Enum = targetDirection; campaign.CampaignTargetTargets.AddRange(targets); if (dueInDays > 0) { campaign.SurveyClosesOn = DateTime.UtcNow.AddDays(decimal.ToDouble(dueInDays)); } var tasks = campaign.Launch(campaign.SurveyClosesOn, taskName).ToList(); if (pause) { foreach (var task in tasks) { context.SetUserTask(task.Cast <BaseUserTask>()); // this will do the save for us. } } else { Entity.Save(tasks); } var responses = tasks.Select(t => t.UserSurveyTaskSurveyResponse); context.SetArgValue(ActivityInstance, GetArgumentKey("core:outLaunchTargetResponses"), responses); // Deal with time-outs. Time-outs can only occur if there is due date and we are pausing. if (pause) { SetTimeoutIfNeeded(context, dueInDays); } // Note that there is no need to set an exit point if we are not pausing as the default exit point will be used. return(!pause); }
/// <summary> /// Runs when the activity is run by the workflow. /// </summary> /// <param name="context">The run state.</param> /// <param name="inputs">The inputs.</param> public void OnRunNow(IRunState context, ActivityInputs inputs) { var startedKey = GetArgumentKey(StartedArgumentAlias); var listKey = GetArgumentKey(ListArgumentAlias); var appIdKey = GetArgumentKey(ApplicationIdArgumentAlias); var appVersionKey = GetArgumentKey(ApplicationVersionArgumentAlias); var ids = new List <Guid>(); var started = context.GetArgValue <bool?>(ActivityInstance, startedKey) ?? false; if (!started) { // set that the activity has started context.SetArgValue(ActivityInstance, startedKey, true); // retrieve the product var productSku = GetArgumentValue <string>(inputs, ProductSkuArgumentAlias); var product = MarketplaceService.GetProduct(productSku); if (product == null) { throw new WorkflowRunException("Product {0} was not found.", productSku); } // process the included apps and app versions and sort their ids ids.AddRange(GetSortedApplicationIds(product)); } else { // retrieve the current state of the ordered list from the context var list = context.GetArgValue <string>(ActivityInstance, listKey); if (!string.IsNullOrEmpty(list)) { ids.AddRange(list.Split(',').Select(Guid.Parse)); } } // loop over the next id on the list var current = ids.FirstOrDefault(); if (current != default(Guid)) { // set the application id and any specific version info on the output var variables = GetAppVariables(context, current); if (variables.Item1 != Guid.Empty) { context.SetArgValue(ActivityInstance, appIdKey, variables.Item1); context.SetArgValue(ActivityInstance, appVersionKey, variables.Item2); } // remove this id from the list and store it again ids = ids.Skip(1).ToList(); var list = string.Join(",", ids); context.SetArgValue(ActivityInstance, listKey, list); context.ExitPointId = new EntityRef(LoopExitPointAlias); } else { // we have finished context.SetArgValue(ActivityInstance, startedKey, false); context.SetArgValue(ActivityInstance, listKey, null); context.ExitPointId = new EntityRef(FinishedExitPointAlias); } }
private const decimal DefaultTimeOutMins = 0; // no time out public override bool OnStart(IRunState context, ActivityInputs inputs) { var assignedTo = GetArgumentEntity <Person>(inputs, "inDisplayFormForUser"); var recordToPresent = GetArgumentEntity <UserResource>(inputs, "inDisplayFormResource"); var form = GetArgumentEntity <CustomEditForm>(inputs, "inDisplayFormForm"); var timeoutDays = GetArgumentValue <decimal>(inputs, "inDisplayFormTimeOut", DefaultTimeOutMins); var priority = GetArgumentEntity <EventEmailPriorityEnum>(inputs, "inDisplayFormPriority"); var activityInstanceAs = ActivityInstance.Cast <DisplayFormActivity>(); var percentageCompleted = GetArgumentValue <decimal?>(inputs, "inDisplayFormPercentageCompleted", null); var waitForNext = GetArgumentValue <bool>(inputs, "inDisplayFormWaitForNext", false); var recordHistory = GetArgumentValue <bool>(inputs, "inDisplayFormRecordHistory", false); var hideComment = GetArgumentValue <bool>(inputs, "inHideComment", false); var openInEditMode = GetArgumentValue <bool>(inputs, "inOpenInEditMode", false); priority = priority ?? Entity.Get <EventEmailPriorityEnum>(new EntityRef("core", "normalPriority")); var workflowRun = context.WorkflowRun; var dueDate = DateTime.UtcNow.AddDays((double)timeoutDays); var userTask = new DisplayFormUserTask { Name = ActivityInstance.Name ?? DefaultTitle, RecordToPresent = recordToPresent, FormToUse = form, AvailableTransitions = GetAvailableUserTransitions(), AssignedToUser = assignedTo, TaskPriority = priority, TaskStatus_Enum = TaskStatusEnum_Enumeration.TaskStatusNotStarted, PercentageCompleted = percentageCompleted, WaitForNextTask = waitForNext, UserTaskDueOn = dueDate, HideComment = hideComment, OpenInEditMode = openInEditMode, DfutLinkToken = CryptoHelper.GetRandomPrintableString(8) }; context.SetUserTask(userTask.Cast <BaseUserTask>()); if (recordHistory) { CreateLogEntry(context, userTask); } SetTimeoutIfNeeded(context, timeoutDays); var tenantSetting = Entity.Get <TenantGeneralSettings>(WellKnownAliases.CurrentTenant.TenantGeneralSettingsInstance); if (Factory.FeatureSwitch.Get("enableWfUserActionNotify")) { // // IN PROGRESS - Please leave // This code is in development and switched off until email and SMS approvals are required by PM. // Notifier notifier = null; // tenantSetting.UserActionNotifier; if (notifier != null) { // TODO: Format correctly for where it is being sent SMS email etc. Move the decision out of here and make the notfier decide on the type of message var generator = new HtmlGenerator(); string message = null; if (notifier.Is <EmailNotifier>()) // TODO: This is wrong, it should be somehow tied to the Router { var transitionOptions = userTask.AvailableTransitions.Select(t => t.FromExitPoint.Name).Where(n => !String.IsNullOrEmpty(n)); if (transitionOptions.Any()) { message = generator.GenerateSelectionPage(userTask); } } else if (notifier.Is <TwilioNotifier>()) { message = generator.GenerateSelectionPageUrl(userTask.DfutLinkToken); } if (message != null) { var userList = userTask.AssignedToUser.ToEnumerable(); var notification = new Notification { NMessage = message }; //TOOD: Add alternative text in the email with a link to the SMS page NotificationRouter.Instance.Send(notifier, notification, userList, false); } } } context.SetArgValue(ActivityInstance, GetArgumentKey("core:outDisplayFormUserTask"), userTask); context.SetArgValue(ActivityInstance, GetArgumentKey("core:dfaInternalKeepHistory"), recordHistory); return(false); }