/// <summary> /// Updates the email status. /// </summary> /// <param name="actionGuid">The action unique identifier.</param> /// <param name="status">The status.</param> /// <param name="emailEventType">Type of the email event.</param> /// <param name="rockContext">The rock context.</param> /// <param name="ProcessWorkflow">if set to <c>true</c> [process workflow].</param> public static void UpdateEmailStatus(Guid actionGuid, string status, string emailEventType, RockContext rockContext, bool ProcessWorkflow) { var action = new WorkflowActionService(rockContext).Get(actionGuid); if (action != null && action.Activity != null) { string attrKey = action.ActionTypeCache.Guid.ToString() + "_EmailStatus"; action.Activity.LoadAttributes(rockContext); string currentStatus = action.Activity.GetAttributeValue(attrKey); // Sometimes Clicked events are reported before opens. If this is the case, do not update the status from clicked to opened. bool updateStatus = true; if (status == OPENED_STATUS && currentStatus == CLICKED_STATUS) { updateStatus = false; } if (!string.IsNullOrWhiteSpace(emailEventType) && (emailEventType != status || !updateStatus)) { action.AddLogEntry(string.Format("Email Event Type: {0}", emailEventType), true); } if (updateStatus) { action.Activity.SetAttributeValue(attrKey, status); action.Activity.SaveAttributeValues(rockContext); action.AddLogEntry(string.Format("Email Status Updated to '{0}'", status), true); } Guid?activityGuid = null; switch (status) { case OPENED_STATUS: { activityGuid = GetActionAttributeValue(action, "OnOpenActivity").AsGuid(); break; } case CLICKED_STATUS: { activityGuid = GetActionAttributeValue(action, "OnClickedActivity").AsGuid(); break; } case FAILED_STATUS: { activityGuid = GetActionAttributeValue(action, "OnFailedActivity").AsGuid(); break; } } if (activityGuid.HasValue) { var workflow = action.Activity.Workflow; var activityType = WorkflowActivityTypeCache.Get(activityGuid.Value); if (workflow != null && activityType != null) { WorkflowActivity.Activate(activityType, workflow); action.AddLogEntry(string.Format("Activated new '{0}' activity", activityType.ToString())); if (ProcessWorkflow) { List <string> workflowErrors; new WorkflowService(rockContext).Process(workflow, out workflowErrors); } } } } }
protected void btnUpdate_Click(object sender, EventArgs e) { var errors = new List <string>(); RockContext rockContext = new RockContext(); var workflows = GetWorkflows(rockContext); //Get the new attribute values from the repeater Dictionary <string, string> attributeUpdates = GetNewAttributeValues(); if (attributeUpdates.Any()) { var mergeFields = LavaHelper.GetCommonMergeFields(this.RockPage, this.CurrentPerson); foreach (var workflow in workflows) { //Reuse the mergefields with new workflow mergeFields["Workflow"] = workflow; //We will store the attribute value changes and apply them all at once Dictionary <string, string> toUpdate = new Dictionary <string, string>(); foreach (var update in attributeUpdates) { toUpdate[update.Key] = update.Value.ResolveMergeFields(mergeFields); //if (toUpdate[update.Key]) //{ //} } foreach (var update in toUpdate) { workflow.SetAttributeValue(update.Key, update.Value); } workflow.SaveAttributeValues(); } } //Workflow settings //Activate the workflows if requested or if a new activity is activated if (ddlState.SelectedValue == "NotComplete" || ddlActivities.SelectedValue.IsNotNullOrWhiteSpace()) { foreach (var workflow in workflows) { workflow.CompletedDateTime = null; } } else if (ddlState.SelectedValue == "Complete") { foreach (var workflow in workflows) { workflow.MarkComplete(); } } //Update Status message if (tbStatus.Text.IsNotNullOrWhiteSpace()) { var mergeFields = LavaHelper.GetCommonMergeFields(this.RockPage, this.CurrentPerson); foreach (var workflow in workflows) { mergeFields["Workflow"] = workflow; workflow.Status = tbStatus.Text.ResolveMergeFields(mergeFields); } } //Activate New Activity int?activityTypeId = ddlActivities.SelectedValueAsId(); if (activityTypeId.HasValue) { var activityType = WorkflowActivityTypeCache.Get(activityTypeId.Value); if (activityType != null) { foreach (var workflow in workflows) { var activity = WorkflowActivity.Activate(activityType, workflow, rockContext); activity.Guid = Guid.NewGuid(); foreach (var action in activity.Actions) { action.Guid = Guid.NewGuid(); } } } } rockContext.SaveChanges(); //Process workflows List <string> errorMessages = new List <string>(); if (workflows.Where(w => w.IsActive).Any()) { foreach (var workflow in workflows) { WorkflowService workflowService = new WorkflowService(new RockContext()); workflowService.Process(workflow, out errorMessages); } } pnlConfirmation.Visible = false; pnlDisplay.Visible = false; pnlDone.Visible = true; }
protected void btnReopen_Command(object sender, CommandEventArgs e) { using (RockContext rockContext = new RockContext()) { WorkflowService workflowService = new WorkflowService(rockContext); Workflow workflow = workflowService.Get(e.CommandArgument.ToString().AsInteger()); if (workflow != null && !workflow.IsActive) { workflow.Status = "Active"; workflow.CompletedDateTime = null; // Find the summary activity and activate it. WorkflowActivityType workflowActivityType = workflow.WorkflowType.ActivityTypes.Where(at => at.Name.Contains("Summary")).FirstOrDefault(); WorkflowActivity workflowActivity = WorkflowActivity.Activate(WorkflowActivityTypeCache.Get(workflowActivityType.Id, rockContext), workflow, rockContext); } rockContext.SaveChanges(); } BindGrid(); }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages) { errorMessages = new List <string>(); double hoursElapsed = HoursElapsed(action); string emailStatus = EmailStatus(action); if (hoursElapsed <= 0) { SendEmail(rockContext, action); } else { var timedOut = false; WorkflowActivityTypeCache unopenedActivityType = null; int? unopenedTimeout = null; Guid?guid = GetAttributeValue(action, "UnopenedTimeoutActivity").AsGuidOrNull(); if (guid.HasValue) { unopenedActivityType = WorkflowActivityTypeCache.Get(guid.Value); unopenedTimeout = GetAttributeValue(action, "UnopenedTimeoutLength").AsIntegerOrNull(); if (emailStatus != OPENED_STATUS && emailStatus != CLICKED_STATUS && unopenedActivityType != null && unopenedTimeout.HasValue && unopenedTimeout.Value < hoursElapsed) { action.AddLogEntry("Unopened Timeout Occurred", true); WorkflowActivity.Activate(unopenedActivityType, action.Activity.Workflow, rockContext); timedOut = true; } } WorkflowActivityTypeCache noActionActivityType = null; int?noActionTimeout = null; guid = GetAttributeValue(action, "NoActionTimeoutActivity").AsGuidOrNull(); if (guid.HasValue) { noActionActivityType = WorkflowActivityTypeCache.Get(guid.Value); noActionTimeout = GetAttributeValue(action, "NoActionTimeoutLength").AsIntegerOrNull(); if (emailStatus != CLICKED_STATUS && noActionActivityType != null && noActionTimeout.HasValue && noActionTimeout.Value < hoursElapsed) { action.AddLogEntry("No Action Timeout Occurred", true); WorkflowActivity.Activate(noActionActivityType, action.Activity.Workflow, rockContext); timedOut = true; } } if (timedOut) { UpdateEmailStatus(action.Guid, TIMEOUT_STATUS, string.Empty, rockContext, false); return(true); } } return(false); }
/// <summary> /// Updates any Cache Objects that are associated with this entity /// </summary> /// <param name="entityState">State of the entity.</param> /// <param name="dbContext">The database context.</param> public void UpdateCache(EntityState entityState, Data.DbContext dbContext) { WorkflowTypeCache.UpdateCachedEntity(this.WorkflowTypeId, EntityState.Modified); WorkflowActivityTypeCache.UpdateCachedEntity(this.Id, entityState); }
/// <summary> /// Gets the cache object associated with this Entity /// </summary> /// <returns></returns> public IEntityCache GetCacheObject() { return(WorkflowActivityTypeCache.Get(this.Id)); }
/// <summary> /// Updates any Cache Objects that are associated with this entity /// </summary> /// <param name="entityState">State of the entity.</param> /// <param name="dbContext">The database context.</param> public void UpdateCache(EntityState entityState, Rock.Data.DbContext dbContext) { AttributeCache.UpdateCachedEntity(this.Id, entityState); AttributeCache.UpdateCacheEntityAttributes(this, entityState); int? entityTypeId; string entityTypeQualifierColumn; string entityTypeQualifierValue; if (entityState == EntityState.Deleted) { entityTypeId = originalEntityTypeId; entityTypeQualifierColumn = originalEntityTypeQualifierColumn; entityTypeQualifierValue = originalEntityTypeQualifierValue; } else { entityTypeId = this.EntityTypeId; entityTypeQualifierColumn = this.EntityTypeQualifierColumn; entityTypeQualifierValue = this.EntityTypeQualifierValue; } if ((!entityTypeId.HasValue || entityTypeId.Value == 0) && string.IsNullOrEmpty(entityTypeQualifierColumn) && string.IsNullOrEmpty(entityTypeQualifierValue)) { GlobalAttributesCache.Remove(); } if ((!entityTypeId.HasValue || entityTypeId.Value == 0) && entityTypeQualifierColumn == Attribute.SYSTEM_SETTING_QUALIFIER && string.IsNullOrEmpty(entityTypeQualifierValue)) { Rock.Web.SystemSettings.Remove(); } if (entityTypeId.HasValue) { if (entityTypeId == EntityTypeCache.GetId <Block>()) { // Update BlockTypes/Blocks that reference this attribute if (entityTypeQualifierColumn.Equals("BlockTypeId", StringComparison.OrdinalIgnoreCase)) { int?blockTypeId = entityTypeQualifierValue.AsIntegerOrNull(); if (blockTypeId.HasValue) { BlockTypeCache.FlushItem(blockTypeId.Value); foreach (var blockId in new BlockService(dbContext as RockContext).GetByBlockTypeId(blockTypeId.Value).Select(a => a.Id).ToList()) { BlockCache.FlushItem(blockId); } } } } else if (entityTypeId == EntityTypeCache.GetId <DefinedValue>()) { // Update DefinedTypes/DefinedValues that reference this attribute if (entityTypeQualifierColumn.Equals("DefinedTypeId", StringComparison.OrdinalIgnoreCase)) { int?definedTypeId = entityTypeQualifierValue.AsIntegerOrNull(); if (definedTypeId.HasValue) { DefinedTypeCache.FlushItem(definedTypeId.Value); foreach (var definedValueId in new DefinedValueService(dbContext as RockContext).GetByDefinedTypeId(definedTypeId.Value).Select(a => a.Id).ToList()) { DefinedValueCache.FlushItem(definedValueId); } } } } else if (entityTypeId == EntityTypeCache.GetId <WorkflowActivityType>()) { if (entityTypeQualifierColumn.Equals("ActivityTypeId", StringComparison.OrdinalIgnoreCase)) { int?activityTypeId = entityTypeQualifierValue.AsIntegerOrNull(); if (activityTypeId.HasValue) { WorkflowActivityTypeCache.FlushItem(activityTypeId.Value); } } } else if (entityTypeId == EntityTypeCache.GetId <GroupType>()) { if (entityTypeQualifierColumn.Equals("Id", StringComparison.OrdinalIgnoreCase)) { int?groupTypeId = entityTypeQualifierValue.AsIntegerOrNull(); if (groupTypeId.HasValue) { GroupTypeCache.FlushItem(groupTypeId.Value); } } else if (entityTypeQualifierColumn.Equals("GroupTypePurposeValueId", StringComparison.OrdinalIgnoreCase)) { int?groupTypePurposeValueId = entityTypeQualifierValue.AsIntegerOrNull(); if (groupTypePurposeValueId.HasValue) { foreach (var groupTypeId in GroupTypeCache.All().Where(a => a.GroupTypePurposeValueId == groupTypePurposeValueId.Value).Select(a => a.Id).ToList()) { GroupTypeCache.FlushItem(groupTypeId); } } } } else if (entityTypeId.HasValue) { // some other EntityType. If it the EntityType has a CacheItem associated with it, clear out all the CachedItems of that type to ensure they have a clean read of the Attributes that were Added, Changed or Removed EntityTypeCache entityType = EntityTypeCache.Get(entityTypeId.Value, dbContext as RockContext); if (entityType?.HasEntityCache() == true) { entityType.ClearCachedItems(); } } } }
/// <summary> /// Renders the specified context. /// </summary> /// <param name="context">The context.</param> /// <param name="result">The result.</param> public override void Render(Context context, TextWriter result) { // first ensure that entity commands are allowed in the context if (!this.IsAuthorized(context)) { result.Write(string.Format(RockLavaBlockBase.NotAuthorizedMessage, this.Name)); base.Render(context, result); return; } var attributes = new Dictionary <string, string>(); string parmWorkflowType = null; string parmWorkflowName = null; string parmWorkflowId = null; string parmActivityType = null; /* Parse the markup text to pull out configuration parameters. */ var parms = ParseMarkup(_markup, context); foreach (var p in parms) { if (p.Key.ToLower() == "workflowtype") { parmWorkflowType = p.Value; } else if (p.Key.ToLower() == "workflowname") { parmWorkflowName = p.Value; } else if (p.Key.ToLower() == "workflowid") { parmWorkflowId = p.Value; } else if (p.Key.ToLower() == "activitytype") { parmActivityType = p.Value; } else { attributes.AddOrReplace(p.Key, p.Value); } } /* Process inside a new stack level so our own created variables do not * persist throughout the rest of the workflow. */ context.Stack(() => { using (var rockContext = new RockContext()) { WorkflowService workflowService = new WorkflowService(rockContext); Rock.Model.Workflow workflow = null; WorkflowActivity activity = null; /* They provided a WorkflowType, so we need to kick off a new workflow. */ if (parmWorkflowType != null) { string type = parmWorkflowType; string name = parmWorkflowName ?? string.Empty; WorkflowTypeCache workflowType = null; /* Get the type of workflow */ if (type.AsGuidOrNull() != null) { workflowType = WorkflowTypeCache.Read(type.AsGuid()); } else if (type.AsIntegerOrNull() != null) { workflowType = WorkflowTypeCache.Read(type.AsInteger()); } /* Try to activate the workflow */ if (workflowType != null) { workflow = Rock.Model.Workflow.Activate(workflowType, parmWorkflowName); /* Set any workflow attributes that were specified. */ foreach (var attr in attributes) { if (workflow.Attributes.ContainsKey(attr.Key)) { workflow.SetAttributeValue(attr.Key, attr.Value.ToString()); } } if (workflow != null) { List <string> errorMessages; workflowService.Process(workflow, out errorMessages); if (errorMessages.Any()) { context["Error"] = string.Join("; ", errorMessages.ToArray()); } context["Workflow"] = workflow; } else { context["Error"] = "Could not activate workflow."; } } else { context["Error"] = "Workflow type not found."; } } /* They instead provided a WorkflowId, so we are working with an existing Workflow. */ else if (parmWorkflowId != null) { string id = parmWorkflowId.ToString(); /* Get the workflow */ if (id.AsGuidOrNull() != null) { workflow = workflowService.Get(id.AsGuid()); } else if (id.AsIntegerOrNull() != null) { workflow = workflowService.Get(id.AsInteger()); } if (workflow != null) { if (workflow.CompletedDateTime == null) { /* Currently we cannot activate an activity in a workflow that is currently * being processed. The workflow is held in-memory so the activity we would * activate would not show up for the processor and probably never run. */ if (!workflow.IsProcessing) { bool hasError = false; /* If they provided an ActivityType parameter then we need to activate * a new activity in the workflow. */ if (parmActivityType != null) { string type = parmActivityType.ToString(); WorkflowActivityTypeCache activityType = null; /* Get the type of activity */ if (type.AsGuidOrNull() != null) { activityType = WorkflowActivityTypeCache.Read(type.AsGuid()); } else if (type.AsIntegerOrNull() != null) { activityType = WorkflowActivityTypeCache.Read(type.AsInteger()); } if (activityType != null) { activity = WorkflowActivity.Activate(activityType, workflow); /* Set any workflow attributes that were specified. */ foreach (var attr in attributes) { if (activity.Attributes.ContainsKey(attr.Key)) { activity.SetAttributeValue(attr.Key, attr.Value.ToString()); } } } else { context["Error"] = "Activity type was not found."; hasError = true; } } /* Process the existing Workflow. */ if (!hasError) { List <string> errorMessages; workflowService.Process(workflow, out errorMessages); if (errorMessages.Any()) { context["Error"] = string.Join("; ", errorMessages.ToArray()); } context["Workflow"] = workflow; context["Activity"] = activity; } } else { context["Error"] = "Cannot activate activity on workflow that is currently being processed."; } } else { context["Error"] = "Workflow has already been completed."; } } else { context["Error"] = "Workflow not found."; } } else { context["Error"] = "Must specify one of WorkflowType or WorkflowId."; } RenderAll(NodeList, context, result); } }); }