Once a form is submitted and it needs corrections, is there a way in the process diagram to reroute the form so that way the corrections can be made instead of having the to start completely over with the form.
Question
Question
Replies
If you want to get creative, you can do it with public forms. I have created Forms processes that are submitted by public users (not anonymous) and if it needs to be sent back to them for anything, the information from the initial form is put in a database table with unique identifiers. When the email is sent to the public user, the unique identifiers are included in the link as part of the query string which populates specific fields on the form and performs a database lookup to repopulate the form.
You could get even more creative and basically pause the original Forms instance, send a link to the public user that goes to a separate form where they can enter the requested information and includes a unique identifier for the original Forms instance. Once submitted, it could kick off a workflow that then updates the original instance with the new data or could be assigned to an internal staff member to manually make the changes to the original form.
This is amazing!
I've done this sort of thing before too and it can be very effective, but it definitely falls into the more "advanced" category.
In my case, I added one additional layer to things. The email I sent contains a URL with the guid as a parameter, but I also send a 6-digit PIN.
When the form loads, it checks for a valid guid using a stored procedure, if no valid guid is present it treats it like a new submission, but if the guid is valid it requests the PIN and only returns the data if both match.
For others who haven't tried this, some things to note with this approach are:
- Make sure the unique identifiers are guid and not numeric so they are nonsequential and it's not easy to test for valid values.
- Change a column value or remove the row after submission so the user doesn't resubmit twice and throw a wrench in things
- There's no straightforward way to populate a file upload field from a lookup or workflow so attachments are potential roadblock.
- Avoid doing this with forms that contain even remotely sensitive information. Even if you use a guid identifier, the data is still technically exposed to a public form since obscurity is not security.
This really depends on the nature of your process and who needs to make the corrections. If you're dealing with anonymous submissions (i.e., not logged in) with a Public form, then there is no way to direct it back to the submitter.
However, if you're dealing with authenticated submissions on a non-public form, then you could create a User Task assigned to the initiator and direct the path back to that step. We do this quite often to add a sort of "Revise & Resubmit" step.
Yes, here's an example of one.
In this particular example, everything is handled based on what button the user clicks.
Accounting Review - Can Click "Approve Request" (Approve button) or "Return to Initiator" (Reject button). And they have these outflows:
Re-Process Request - can click "Re-Submit Request" (Submit button) or "Cancel Request" (Reject button). And they have these outflows:
You can also have the flow decision happen via a Gateway instead of directly on the user task. In some cases, this is necessary, based on complexity of the flow decisions (outflows on a user task are basically the same as an Exclusive Gateway - so if you need multiple simultaneous outgoing paths, you'll need to use one of the other gateways).
You can also define the criteria for the flow decisions based on field values and a lot of other criteria, instead of just which button was clicked.
Similar to what Blake stated, we are doing this on external forms too for applications. This way, if information needs to be corrected, the end user doesn't have to start all over. We use a JSON script that saves the field data when the end user hits submit and stores it in a single multiline field.
$('.Submit').click(function(){ //Define Field Types fieldTypes = [ ["text","[attrtype='text'] [id^='Field']:not([readonly])"] ,["longtext","[attrtype='longtext'] [id^='Field']:not([readonly])"] ,["checkbox","[attrtype='checkbox'] :checked:not([readonly])"] ,["checkbox:other","[attrtype='checkbox'] [id$='_other_value']:not([readonly])"] ,["radio","[attrtype='radio'] :checked:not([readonly])"] ,["date","[attrtype='date'] [id^='Field']:not([readonly])"] ,["select","[attrtype='select'] [id^='Field']:not([readonly])"] ,["email","[attrtype='email'] [id^='Field']:not([readonly])"] ,["number","[attrtype='number'] [id^='Field']:not([readonly])"] ] //Don't capture: student_id | login_id | access_token | Saved_Draft_Object | IS_DRAFT nocap = "[attr='SubmissionLogin'] input, [attr='Saved_Draft_Object'] textarea, [attr='FormURL'] input, [attr='Registrationformurl'] input, [attr='curstep'] input, [attr='ApplicationStatus'] input, [attr='K12ReviewComplete'] input" //Save Draft Object to "Saved_Draft_Object" arrayD = [] fieldTypes.forEach(function(x){ $(x[1]).not(nocap).filter(function(x){ return $(this).val() }) .each(function(i){ console.log(x) arrayD.push([x[0],$(this)[0]['id'],$(this).val()]) }) }); $("[attr='Saved_Draft_Object'] textarea").val(JSON.stringify(arrayD)); });
Then it is stored in a SQL table and an email is sent back to the end user with the a link to the same form but it includes variables in the url such as email address and a unique identifier code. Those two variables pull a stored procedure to pull the original data back into the field in the form and restore the fields with the previously saved data.
//update Fields function updateField(type, id, value) { //If value is an array, update each value for the field try { JSON.parse(value).forEach(function(x) { updateField(type, id, x); }); return; } catch (error){} //Checkbox - Radio if (["checkbox", "radio"].includes(type)) { $("[id='" + id + "'] [value='" + value + "']:not(.value-imported)") .prop("checked", true) //.attr("lookupalt","true") .addClass("value-imported") .trigger("change"); } //Text - LongText - Checkbox:Other - Date - Select if (["text", "longtext", "email", "date", "number", "select"].includes(type)) { $("[id='" + id + "']:not(.value-imported)") .val(value) //.attr("lookupalt","true") .addClass("value-imported") .trigger("change"); } } //Restore Draft try { JSON.parse($("[attr='Saved_Draft_Object'] textarea").val()).forEach(function(x){ //Expand Collections mI = x[1].match(/Field\d+\((\d+)\)/); if(mI){ coll = $("[id^='"+x[1].split("(")[0]+"']").closest("[attrtype='table']:not(.value-imported)") if(coll.length && mI[1] > coll.children(".cf-collection").children().length){ coll.children(".cf-collection-append").trigger('click'); } } updateField(x[0],x[1].split(/-|_other$/)[0],x[2]); }); }catch(error){}
If any of your fields are pulling values from sql based on another field value, these values can't be changed so it might not be worth it to have those auto-fill if they are values the user may need to change. It also won't work for attachments, but for the most part it is pretty simplistic and saves a lot of time.
Make sure you write something in to kill the resubmission link and data once its been resent so people don't send it multiple times.