Building a Workflow Engine


One of the most frequently asked questions when it comes to building a Formidable Forms business process is "How do I build a workflow to assign tasks, track sequence completions, and move to next steps?"

Workflows can be complicated. Oftentimes, there are security considerations such as "How can I allow the project manager to see everything, but hide tasks from users unless the task is assigned to them?"

Then there is the notification process. Each time a subsequent task is assigned to a user, they need to be notified that it has been moved into their workflow queue.

This tutorial will walk you through the process we used when a marketing agency hired us to build a simple workflow engine for a local communications company using Formidable. When we accepted the assignment, most of the forms had already been built by the agency. There are some things we would have done differently had we gotten this job at the beginning, but instead of reinventing what had already been done, we worked within the parameters we had been given.

Working with forms built by someone that only has gentle experience with Formidable and no experience building a workflow engine at all doesn't exactly foster an ideal development project. We've worked regularly with this client in the past and have enjoyed doing so, but this time they had no idea what they were biting off by promising their customer a workflow solution.

Their entire project was budgeted at less than what we charge to build a workflow solution for one of our clients. Even a simple workflow solution as demonstrated in this tutorial can cost a business $3,500 to $5,000 USD as ballpark figures. These are also the kind of fees you can charge your clients if you learn how to do this yourself.

So rather than build replicas of the agency's forms, we're going to explain what the forms do and the fields they contain to give you a basic idea of what's involved. We'll include additional descriptions if fields require further explanation.



The project form contains everything you might expect when documenting a project. It has the following fields:

  1. Project name (Text)
  2. Prime (Lookup Customers): customer primary contact
  3. Address Line 1 (Text)
  4. Address Line 2 (Text)
  5. City (Lookup Locations)
  6. State (Lookup Locations)
  7. Zip (Text)
  8. County (Lookup Locations)
  9. Repeater: used to capture additional customer contacts
    • Customer (Lookup Customers)
  10. Service Needed (Radio Buttons): services that can be requested for this project. One service per project please.
  11. Service Description (Rich Text Field): free form description of services requested
  12. Date RFQ Received (Date)
  13. Date Proposal Due (Date)
  14. Due Time (Time)
  15. Fire Authority (Lookup Fire Jurisdiction): fire authority to receive project notifications
  16. Assigned To (Lookup Employees/Contractors)
  17. When to follow-up (Date): follow-up date can be [date offset="+30 days"] or [date offset="+5 days"] depending on the Service Needed value
  18. Project Status (Radio Buttons): values can be In Consideration, Won, or Lost
  19. Archive Project (Toggle): if archive project toggle is active (Yes), project will not display in active project views
  20. Date Entered (Date)
  21. User ID (User ID)
  22. Project Assigned To Email (hidden): populated from WordPress user table and used as filter for project views
  23. Project Assigned To User ID (hidden): populated from WordPress user table and used as filter for project views
  24. Project Assigned To User Error (hidden): populated if something goes wrong with retrieving the assign to user's email, user id, or both

Lookup Tables

These tables are used to provide data to the lookup fields on the project form. The Employees/Contractors form is also used as a lookup to assign people to tasks on the workflow form.

  1. Customers
  2. Employees/Contractors
  3. Fire Jurisdiction
  4. Locations

Workflow Steps

This form is used as a lookup to populate the workflows for a given project service's initialization phase and well as for its Won or Lost status. The design of this form is the key to building a flexible workflow engine where workflow steps may vary for different service types. Fields include:

  1. Services (Checkboxes): Services reflect the Service Needed radio button field on the project form. Checkboxes are used here to allow for multiple services that include the same workflow step.
  2. Project Phase (Radio Buttons): These radio buttons have the same values as the Project Status radio buttons on the project form.
  3. Workflow Step Name (Text)
  4. Workflow Step Sequence (Text): the sequence is used as a sort field for the SQL used to populate the project's workflow. Since this is a test field, start the sequence as 01, 02, 03, ..., etc. so the SQL query sorts the steps correctly.
  5. Consideration (Text): used for any additional notes required for this step
  6. Prior Workflow Step (Text)
  7. Next Workflow Step (Text)

Project Workflow

This is the workflow engine. All workflow steps are created through custom code when a project is created or the project's Project Status radio button field is updated. Fields include:

  1. Name (Test): populated from Workflow Step Name from Workflow Steps form
  2. Assigned To (Lookup Employees/Contractors): full name of emplyee/contractor assigned to this task
  3. Due Date (Date)
  4. Date Completed (Date)
  5. Consideration (Text): used for any additional notes required for this step
  6. Prior Workflow Step (Text)
  7. Next Workflow Step (Text)
  8. Project ID (Hidden): the entry id of the associated project
  9. User ID (User ID)
  10. Assigned To Email (Hidden): populated from WordPress user table, used for email notifications
  11. Assigned To User ID (Hidden): populated from WordPress user table and used as filter for assigned task views
  12. Assigned To User Error (Hidden): populated if something goes wrong with retrieving the assign to user's email, user id, or both
  13. Sequence (Hidden): workflow step sequence from the Workflow Steps entry
  14. Workflow Phase (Hidden): in conjunction with sequence, used for ordering views


Populating the Initial Workflows

The process for this workflow is fairly simple. The user creates a new project and when the form is submitted, we use Formidable's frm_after_create_entry hook to populate the associated workflow form with its initial steps. Here is the source code:

At this point, the initial workflow steps are populated and can be edited. A view is used to display the associated projects and each workflow step can be edited for deleted if not necessary for a specific project.

Assigning the Task to a User

Editing a workflow generally means to make the assignment to an employee or contractor and then assigning the due date. The employee or contractor receives an email documenting the assigned task. They can also visit the site and see all of their assigned tasks with a Formidable view.

It's important to note that the assignment is performed by the project manager. The user id in the workflow record is recorded when the workflow form records are created by the populate_initial_workflow function.

As you know, Formidable views can be filtered by the logged in user's ID. In order for the assignees to see their assignments, we have to record their user ID in the record as well. To accomplish this, we use jQuery to monitor the Assigned To lookup field's change event. When the field changes, we fire an Ajax call that looks up the assigned to's email address and user id and populates hidden fields on the Workflow record.

jQuery Source

This jQuery requires a little explanation. The Assigned To field on the project form has a default value. The Assigned To lookup fields on the Project and Workflow forms are being monitored for their change event. Because the Project form has a default value, the change event doesn't fire unless the assigned project manager changes from the default. The means that the email address and user id for the project manager won't be populated off of the default value.

To overcome this deficiency, the Ajax is fired in the execute_assigned_to_email_ajax() function (line 4). The self executing function, $(function() (line 43), fires when the document is ready. It checks for whether or not the assigned_to_email is populated. If the field is empty, the Ajax fires using the default value. The Assigned To fields on both forms are monitored for their change event and if a change is detected, the Ajax fires.

AJAX Callback PHP Source

Using Project Status to Add Additional Workflow Steps

The project status field on the project form has three possible values: In Consideration, Won, or Lost. The "In Consideration" value is not pertinent to populating the workflow engine, but "Won" or "Lost" are. If the project status is changed to "Won" or "Lost", there are additional workflow steps that are added to the workflow form. To accomplish, we use Formidable's frm_after_update_entry hook. Here is the source code:

Other Considerations

For this to all work well together, the Employees/Contractors must have user IDs. Use Formidable's User Registration add-on to create their WordPress user records.

We recommend using a single form to capture employee and contractor details. A single form makes it much easier to assign a task to a user. You can differentiate contractors from employees by including a toggle or radio buttons field to designate the resource type.

You may have noticed that we have an "assigned to user error" field in the workflow form. This is used to capture any errors that may occur with the Ajax function used to populate the email and user id. Since email address is captured on the employee/contractor form, the biggest issue we anticipate is that there is no user id for the assignee. This can happen if the User Registration add-on is not used with the employee/contractor form.

The Formidable documentation for FrmEntry::create() may be a little off. The PHP example populates form_id, item_key, and frm_user_id among other fields. We found that if you create an entry based on the example code, the entry name is populated with a duplication of the item_key. If you're okay with this, then fine! Don't change anything. But if you don't want the item_key duplicated in the name field, set name => '' as we've done in our example code.


This is a very simple workflow consisting of what we consider the "basics". For some clients, we have built highly complex, secure workflow engines requiring more than 400-man hours of effort. If you are budgeting for a simple workflow like this one, we suggest keeping it within 20-man hours. We invested 15-man hours into this particular project. That time included client meetings, building the required forms, and writing and thoroughly testing the code. Good luck and have fun!

Reader Interactions

Leave a Reply

Your email address will not be published. Required fields are marked *