How to embed forms to the workflow
Overview of workflow
Forms can be embedded into a workflow.
Initially Workflow have nested structure of items, where each item can be:
Section - used for forms grouping.
Form - reference to existed form.
Workflow and items has status model , model is slightly different
Workflow statuses:
new
in-progress
canceled
completed
in-amendment
amended
Item statuses:
new
in-progress
skipped
completed
in-amendment
amended
canceled
status used for WF because skipped
status is not obvious in this domain. WF is a process of action, but item is just a step that can be optionally and can be omitted.
Workflow definition
DemoWF3
;; Tag to mark entity as Workflow
{:zen/tags #{aidbox.sdc/Workflow}
;; title of the WF
:title "Demo workflow"
;; items consists of sections/forms in any level deep
;; section key can be arbitrary keyword
:items {:section1
;; section definition with 2 forms
{:item aidbox.sdc/SectionItem
:title "My custom section 1"
:items {:phisical-exam
;; form item definition.
{:item aidbox.sdc/FormItem
:form VitalsForm}
:questionnaire {:item aidbox.sdc/FormItem
:form PHQ2PHQ9Form}}}}}
When WF is started - it will be populated with items :order
information, launched forms, document's references and state statuses.
DemoWF3
;; Tag to mark entity as Workflow
{:zen/tags #{aidbox.sdc/Workflow}
:title "Demo workflow"
:order [:section1]
:status "new"
:items {:section1 {:item aidbox.sdc/SectionItem
:title "My custom section 1"
:status "new"
:order [:phisical-exam :questionnaire]
:items {:phisical-exam {:item aidbox.sdc/FormItem
:form myforms/Demographic
:title "Demographic"
:layout {... layout DSL}
:rules {... rules ...}
:document {id: doc-id :resourceType}
:status "new"}
:questionnaire {... launched form ...}}}}}
Also see Optional features section for some workflow payload customization.
Section
Section item is item with type aidbox.sdc/SectionItemIt contains
titleand children
items`. These fields are mandatory
{:item aidbox.sdc/SectionItem
:title "My custom Section"
:items {:form1 {:item aidbox.sdc/FormItem
:form myforms./VitalsForm}
:section1 {:item aidbox.sdc/SectionItem
:title "My custom Section"
:items {:form1 {:item aidbox.sdc/FormItem
:form myforms/Demographic}}}}}
When workflow is started - all SectionItems
will be populated with meta information of items order.
Order generated from
:items
natural placement in ZEN file.
{:item aidbox.sdc/SectionItem
:title "My custom Section"
:order [:form1 :section1]
:items {:form1 {:item aidbox.sdc/FormItem
:form myforms./VitalsForm}
:section1 {:item aidbox.sdc/SectionItem
:title "My custom Section"
:order [:form1]
:items {:form1 {:item aidbox.sdc/FormItem
:form myforms/Demographic}}}}}
Form
FormItem is item with type aidbox.sdc/FormItem
It contains only reference to existed form
. This field is mandatory
{:item aidbox.sdc/FormItem
:form myforms/Demographic}
Zen validates reference - it can refer to symbols with
aidbox.sdc/Form
tag only.
When workflow is started - all FormItems
will be populated with Form
definition, Launched Layout
, form+document rules and reference to created Document
.
{:item aidbox.sdc/FormItem
:form myforms/Demographic
:title "Demographic"
:layout {... layout DSL}
:rules {... rules ...}
:document {id: doc-id :resourceType}}
StatelessForm
StatelessForm is item with type aidbox.sdc/StatelessFormItem
It contains only reference to existed form
. This field is mandatory
It is different from typical FormItem
in that way:
data populated to it's state on every read-workflow operation.
data extracted and populated back on every save operation.
this form can't be skipped.
{:item aidbox.sdc/StatelessFormItem
:form myforms/AllergyIntolerance}
Zen validates reference - it can refer to symbols with
aidbox.sdc/Form
tag only.
There is no difference between StatelessFormItems
and FormItem
on workflow-start
{:item aidbox.sdc/StatelessFormItem
:form myforms/AllergyIntolerance
:title "AllergyIntolerance"
:layout {... layout DSL}
:rules {... rules ...}
:document {id: doc-id :resourceType}}
Form rule keys
FormItem also supports special rule based keys: sdc/inject
, sdc/enable-when
:sdc/inject
used for injecting values to form context.
This rule is client side rule. You don't have access to DB.
This rule is invoked on each time when form is focused.
Value of the :sdc/inject
key should be rules map - where key should match expected key by form's rules, and value is a lisp expression. Lisp expressions are invoked in the context of workflow state.
{:item aidbox.sdc/SectionItem
:title "My custom Section"
:order [:form1 :form2]
:items {:form1 {:item aidbox.sdc/FormItem
:form myforms./VitalsForm}
:form2 {:item aidbox.sdc/FormItem
:sdc/inject {:vitals/bmi (get-in [:items :form1 :document :bmi])}
:form myforms/Demographic}}}
;; myforms namespace
DemographicDocument
{:zen/tags #{aidbox.sdc/doc}
:sdc/rules {:external-bmi (get :vitals/bmi)}
...}
Demographic
{:zen/tags #{aidbox.sdc/Form}
:document DemographicDocument
...}
:sdc/enable-when
used in situations when you have optional forms.
The rule is used on the client to show/hide the form
The rule is used on the server
to launch forms without storing SDCDocuments in DB.
to validate form optionality on the complete-workflow/complete-step rpcs
Value of the key :sdc/enable-when
should be boolean lisp expression. Lisp expression is invoked in the context of workflow state.
{:item aidbox.sdc/SectionItem
:title "My custom Section"
:order [:form1 :form2]
:items {:form1 {:item aidbox.sdc/FormItem
:form myforms./VitalsForm}
:form2 {:item aidbox.sdc/FormItem
:sdc/enable-when (> (get-in [:items :form1 :document :bmi]) 5)
:form myforms/Demographic}}}
Basic WF usage scenarios
Assume we have such WF with one section and two forms
DemoWF
{:zen/tags #{aidbox.sdc/Workflow}
:title "Demo workflow"
:version "0.0.1"
:items {:section1 {:item aidbox.sdc/SectionItem
:title "My custom section 1"
:items {:phisical-exam {:item aidbox.sdc/FormItem
:form VitalsForm}
:questionnaire {:item aidbox.sdc/FormItem
:form PHQ2PHQ9Form}}}}}
From the start (after WF start) we are working with form-items directly via step functions (step-save/step-complete/step-skip) When form-items pushed to some final state (completed/skipped) - sections will complete/skip automatically. And as final action - you need to complete/cancel workflow.
Fast forward scenario
Fast skip scenario
Optional features
Workflow support 2 additional features:
versioning
- is automatic and based on hashing essential fields of definitions. If some essential field of form/wf is changed - created a new version and snapshotted to DBsection id generation -
is generated from item path (path from WF root to item itself).
These features you can configure via api-constructor in zen-project.
You need to configure your aidbox/system
with sdc-service
and it's configuration
Your zen-project entrypoint namespace
aidbox/system
with sdc-service
box
{:zen/tags #{aidbox/system}
:zen/desc "test server"
:services {:sdc sdc-service}}
sdc-service
configuration
sdc-service
;; bind your sdc/service with engine `aidbox.sdc/service`
{:zen/tags #{aidbox/service}
:engine aidbox.sdc/service
;; Enable Form/Workflow versioning
:versioning {:enabled false}
;; Enable WF items id generation
:wf-items-ids-gen {:enabled true}}
Section id generation
When :wf-items-ids-gen
feature is enabled - each section will receive :id
property. That id returned on start-workflow
, read-workflow
rpc payloads, and don't affect WF storage.
Id is generated from item path (path from WF root to item itself).
Example:
This WF definition
{:zen/tags #{aidbox.sdc/Workflow}
:title "My Workflow"
:items {:section1 {:item aidbox.sdc/SectionItem
:items {:phisical-exam {:item aidbox.sdc/FormItem
:form VitalsForm}
:questionnaire {:item aidbox.sdc/FormItem
:form PHQ2PHQ9Form}}}}}
on start-workflow
/read-workflow
rpcs call - adds items :id information to payload
{:title "My Workflow"
:items {:section1 {:id "section1"
:items {:phisical-exam {... :id "section1.phisical-exam" ...}
:questionnaire {... :id "section1.questionnaire" ...}}
...}}}
You can use Workflow API
get-workflow - get workflow definition
get-workflows - return existed workflows
start-workflow - start WF and launch forms
save-step - save document through WF, mark step as in-progress
skip-step - skip WF step
amend-step - amend WF step
complete-step - try complete WF step with document, call sign on it.
complete-workflow - complete WF
cancel-workflow - try cancel WF
amend-workflow - amend completed WF
add-workflow-note - add addendum note to the given WF
get-workflow-addendums - get list of addendums for the given WF
Last updated
Was this helpful?