Form-driven workflow engine. Making city government better, one form at a time.
Government agencies, like many organizations, have a ton of processes. If an employee wants to attend a conference and needs travel reimbursement, their supervisor must approve, then their director must approve, and if it costs more than $500, the CFO must approve. New hire on-boarding consists of several steps that can happen in parallel.
In many cases, there is already software out there -- especially in the HR world -- that handle these processes. When they're available, you should use them. But when there isn't software already available, or the agency doesn't have access to it, the processes still exist; they just take place over email. Stately is for these processes.
Eventually, we'd like Stately to have a user-friendly web interface for designing forms and workflows. For now, it's driven by a configuration file that looks like this:
name: Travel Request
states:
- name: Not started
actions:
- name: Initiate
template:
fields:
- name: Name
- name: Initiator Email
- name: Destination
- name: Cost
- name: Supervisor Email
handler: |
change_state('Awaiting Supervisor Approval')
assign(data.supervisor_email, send_email=True)
- name: Awaiting Supervisor Approval
actions:
- name: Approve
handler: |
if (data.cost) >= 500:
change_state('Awaiting CFO Approval')
assign(cfo_email, send_email=True)
else:
change_state('Approved')
assign(data.initiator_email, send_email=True)
- name: Reject
# ...... (see the rest in workflows/travel-request.yml)
This renders a form that, when submitted, kicks off the handler
, changing
the state of the request and sending emails to reviewers with unique access
tokens.
The aim of this approach is to provide a balance between configurability and flexibility, accommodating many workflows out-of-the-box, with an option to write basic python code for any advanced / edge-case workflows.
We're building with the following use cases from Philadelphia City Government in mind. Have your own that comes to mind? Tell us about it.
- Leave request
- employee submits form, manager approves, entry is able to be looked up later
- Travel reimbursement request
- like leave request, but director must also approve, and if >$500, CFO must approve
- New hire onboarding
- multiple tasks that can be completed asynchronously. perhaps when all 3 tasks are done, the 4th task is able to begin
- Contract
- Document-oriented (w/signature) vs content-oriented
- Freedom of Information Act request
- public submits form, can track its progress, assigned based on department field, can be re-assigned, auto-reply if not fulfilled in 5 business days, requests can be shared publicly like forum posts
- New-hire Indebtedness Check (ensure new hires don't owe the city money)
- HR manager enters a candidate for employment, and reps from various departments verify that the candidate does not owe any money to the city
Brainstorming, API spec, etc. is on a hackpad
The client application requires Node JS to build.
Install dependencies by navigating into the client
directory in the terminal and run:
npm install
Afterwards, run a local development server using:
npm start
The server application requires python. It is recommended that you create a
virtual environment
before installing dependencies. Once you've activated your virtual environment,
install dependencies by navigating to the server
directory and running:
pip install .
Then setup the database using:
python src/manage.py migrate
Load the workflow files from the workflows
directory into the database using:
python src/manage.py workflow_load ../workflows/*
Check the workflows that are loaded into the database using:
python src/manage.py workflow_list
Finally, run the server using:
python src/manage.py runserver