22.5 Configure program rules

22.5.1 About program rules

Program rules allows you to create and control dynamic behavior of the user interface in the Tracker Capture and Event Capture apps. During data entry, the program rules expressions are evaluated each time the user interface is displayed, and each time a data element is changed. Most types of actions will take effect immediately when the user enters values in the Tracker Capture and Event Capture apps.

Program rule components

Program rule component

Description

Program rule action

Each program rule contains one or multiple actions. These are the behaviors that are triggered in the user interface when the expression is true. Actions will be applied at once if the expression is true, and will be reverted if the expression is no longer true. There are several types of actions and you can have several actions in one program rule.

Program rule expression

Each program rule has a single expression that determines whether the program rule actions should be triggered, if the expression evaluates to true. If the expression is true the program rule is in effect and the actions will be executed. If the expression is false, the program rule is no longer in effect and the actions will no longer be applied.

You create the expression with standard mathematical operators, custom functions, user-defined static values and program rule variables. The program rule variables represent attribute and data element values which will be evaluated as part of the expression.

Program rule variable

Program rule variables lets you include data values and attribute values in program rule expressions. Typically, you’ll have to create one or several program rule variables before creating a program rule. This is because program rules expressions usually contain at least one data element or attribute value to be meaningful.

The program rule variables are shared between all rules in your program. When you create multiple program rules for the same program, these rules will share the same library of program rule variables.

In the Maintenance app, you manage the following program rule objects:

Object type

Available functions

Program rule

Create, edit, clone, delete, show details and translate

Program rule variable

Create, edit, clone, share, delete, show details and translate

22.5.2 Workflow

  1. In the Maintenance app, create program rule variable(s) if needed.

  2. In the Maintenance app, create the program rule:

    1. Enter the program rule details.

    2. Create the program rule expression.

    3. Define the program rule actions.

  3. In the Tracker Capture or Event Capture apps, verify that the program rule behaves as expected.

22.5.3 Create or edit a program rule variable

  1. Open the Maintenance app and click Program > Program rule variable .

  2. Click the add button.

  3. Select a Program and enter a Name .

  4. Select if you want to Use code for option set .

    This option is only effective when the data element or tracked entity attribute is connected to an option set. If you don’t select this option, the program rule variable will be populated with the option set’s name. If you select the option, the program rule variable will be populated with the option set’s code instead.

  5. Select a Source type and enter the required information.

    Depending on the source type, you’ll have to select, for example, a Program stage, Data element or Tracked entity attribute .

    The source types determine how the program rule variable is populated with a value.

    Source type

    Description

    Data element from the newest event for a program stage

    This source type works the same way as Data element from the newest event in the current program , except that it only evaluates values from one program stage.

    This source type can be useful in program rules where the same data element is used in several program stages, and a rule needs to evaluate the newest data value from within one specific stage.

    Data element from the newest event in the current program

    This source type is used when a program rule variable needs to reflect the newest known value of a data element, regardless of what event the user currently has open.

    This source type is populated slightly differently in Tracker Capture and Event Capture apps:

    Tracker Capture : the program rule variable will be populated with the newest data value collected for the given data element within the enrollment.

    Event Capture : the program rule variable will be populated with the newest data value found within the 10 newest events in the same organisation unit.

    The newest data value is determined with event date.

    Data element in current event

    Program rule variables with this source type will contain the data value from the same event that the user currently has open.

    This is the most commonly used source type, especially for skip logic (hide actions) and warning/error rules.

    Data element from previous event

    Program rule variables with this source type will contain the value from a specified data element from a previous event. Only older events is evaluated, not including the event that the user currently has open.

    This source type is commonly used when a data element only should be collected once during an enrollment, and should be hidden in subsequent events.

    Another use case is making rules for validating input where there is an expected progression from one event to the next - a rule can evaluate whether the previous value is higher/lower and give a warning if an unexpected value is entered.

    This source type is populated slightly differently in Tracker Capture and Event Capture apps:

    Tracker Capture : the program rule variable will be populated with the newest data value collected for the given data element within the enrollment - but only evaluating the events that comes before the current event date.

    Event Capture : the program rule variable will be populated with the newest data value collected within the 10 events preceding the current event date - not including the current event.

    The newest data value is determined with event date.

    Calculated value

    TBA

    Tracked entity attribute

    Populates the program rule variable with a specified tracked entity attribute for the current enrollment.

    Use this is the source type to create program rules that evaluate data values entered during registration.

    This source type is also useful when you create program rules that compare data in events to data entered during registration.

    This source type is only used for tracker programs (programs with registration).

  6. Click Save .

22.5.4 Create or edit a program rule

Note

A program rule belongs to exactly one program.

  1. Open the Maintenance app and click Program > Program rule .

  2. Click the add button.

  3. Enter the program rule details. These fields are not shown to the end user, they are only meant for the program administrator.

    • Program

    • Name

    • Description

    • Priority

      Let’s say you have 16 program rules in your program. You configure the program rules with the following priority settings:

      • Priority 1 for program rule A

      • Priority 2 for program rules B - K

      • No priority for program rules L - P

      Result: the system runs the program rules in the following order:

      1. Program rule A

      2. Program rules B - K (you can’t find out or configure in which order the system runs these program rules)

      3. Program rules L - P.

  4. Click Enter program rule expression and create the program rule expression with the help of variables, functions and operators.

  5. Click Define program rule actions and create the actions executed when the expression is true.

    1. Click the add button, select an Action and enter the required information.

      Depending on the action type, you’ll have to perform different types of settings. For some action types, you must also enter free text or create expressions.

      Action type

      Required settings

      Description

      Assign value

      Data element to assign value to

      Program rule variable to assign value to

      Expression to evaluate and assign

      Used to help the user calculate and fill out fields in the data entry form. The idea is that the user shouldn’t have to fill in values that the system can calculate, for example BMI.

      When a field is assigned a value, the user sees the value but the user can’t edit it.

      Example from Immunization stock card i Zambia: The data element for vaccine stock outgoing balance is calculated based on the data element for incoming stock balance minus the data elements for consumption and wastage.

      Advanced use: configure an ‘assign value’ to do a part of a calculation and then assign the result of the calculation to a program rule variable. This is the purpose with the “Calculated value” program rule variable.

      Display text

      Display widget

      Static text

      Expression to evaluate and display after static text

      Used to display information that is not an error or a warning, for example feedback to the user. You can also use this action to display important information, for example the patient’s allergies, to the user.

      Display key/value pair

      Display widget

      Key label

      Expression to evaluate and display as value

      Used to display information that is not an error or a warning.

      Example: calculate number of weeks and days in a pregnancy and display it in the format the clinician is used to see it in. The calculation is based on previous recorded data.

      Error on complete

      Data element to display error next to

      Tracked entity attribute to display error next to

      Static text

      Expression to evaluate and display after static text

      Used whenever you’ve cross-consistencies in the form that must be strictly adhered to. This action prevents the user from continuing until the error is resolved.

      This action differs from the regular Show error since the error is not shown until the user tries to actually complete the form.

      If you don’t select a data element or a tracked entity attribute to display the error next to, make sure you write a comprehensive error message that helps the user to fix the error.

      Hide field

      Data element to hide

      Tracked entity attribute to hide

      Custom message for blanked field

      Used when you want to hide a field from the user.

      Custom message for blanked field allows you to define a custom message displayed to the user in case the program rule hides and blanks out the field after the user typed in or selected a value.

      If a hide field action hides a field that contains a value, the field will always removed. If no message is defined, a standard message will be displayed to alert the user.

      Hide section

      Program stage section to hide

      TBA

      Hide program stage

      Program stage to hide

      Used when you want to hide a program stage section from the user.

      Make field mandatory

      Data element to make mandatory

      Tracked entity attribute to make mandatory

      TBA

      Show error

      Data element to display error next to

      Tracked entity attribute to display error next to

      Static text

      Expression to evaluate and display after static text

      Used whenever there are rules which must strictly be adhered to. The show error action prevents the user from continuing until the error is resolved.

      Such a strict validation should only be used when it’s certain that the evaluated expression is never true unless the user has made a mistake in data entry.

      It’s mandatory to define a message that is shown to the user when the expression is true and the action is triggered.

      You can select which data element or tracked entity attribute to link the error to. This will help the user to fix the error.

      In case several data elements or attributes are involved, select the one that is most likely that the user would need to change.

      Show warning

      Data element to display warning next to

      Tracked entity attribute to display warning next to

      Static text

      Expression to evaluate and display after static text

      Used to give the user a warning about the entered data, but at the same time to allow the user to save and continue.

      You can use warnings to help the user avoid errors in the entered data, while at the same time allow the user to consciously disregard the warnings and save a value that is outside preset expectations.

      Static text defines the message shown to the user when the expression is true and the action is triggered.

      You can select which data element or tracked entity attribute to link the error to. This will help the user to fix the error.

      In case several data elements or attributes are involved, select the one that is most likely that the user would need to change.

      Warning on complete

      Data element to display warning next to

      Tracked entity attribute to display warning next to

      Static text

      Expression to evaluate and display after static text

      Used to give the user a warning if he/she tries to complete inconsistent data, but at the same time to allow the user to continue. The warning is shown in a dialog when the user completes the form.

      Static text defines the message shown to the user when the expression is true and the action is triggered. This field is mandatory.

      You can select which data element or tracked entity attribute to link the error to. This will help the user to fix the error.

      If you don’t select a data element or a tracked entity attribute to display the error next to, make sure you write a comprehensive error message that helps the user to fix the error.

      Send Message

      Message template to send

      Send Message triggers a notification based on provided message template. This action will be taken at event/enrollment completion.

      Message template will be parsed and variables will be substituted with actual values.

    2. Click Save .

    3. (Optional) Repeat above steps to add more actions.

  6. Click Save .

22.5.5 Example: Program rules

Note

You can view all examples on the demo server: https://play.dhis2.org/dev/dhis-web-maintenance/#/list/programSection/programRule

This example shows how to configure a program rule which calculate number of weeks and days in a pregnancy and display the result in the format the clinician is used to see it in. The calculation is based on previous recorded data.

  1. The full expression in the Data field:

    d2:concatenate(d2:weeksBetween(#{lmp}, V{current_date}), '+',
    d2:modulus(d2:daysBetween(#{lmp}, V{current_date}), 7))

This example shows how to configure a program rule to display text in the Feedback widget in the Tracker Capture app.

This example shows how to configure a program rule to always display certain data in the Feedback widget in the Tracker Capture app. This is useful when you want to make sure that vital data, for example medicine allergies, is always visible.

By using a program rule of type “Assign value” you can calculate the “Gestational age at visit” value and fill it in the data entry form. You configure the program rule to calculate “Gestational age at visit” based on either “LMP date” or “Ultrasound estimated due date”.

22.5.6 Reference information: Operators and functions to use in program rule expression

Tip

You can nest functions within each other and with subexpressions to form more complex conditions. An example that produces the gestational age in weeks, based on last menstrual date:

d2:floor( d2:daysBetween(#{lastMenstrualDate},V{event_date}) / 7 )

Tip

The source type will determine how the d2: function calls will evaluate a (sourcefield) parameter.

Example: where #{hemoglobinCurrent} is set to source type Data element in current event . The following function call with evaluate whether hemoglobin is entered in the current event.

d2:hasValue( 'hemoglobinCurrent' )

Example: where #{hemoglobin} is set to source type Data element from the newest event in the current program . The following function call with evaluate whether there exists a value for the hemoglobin in any event in the enrollment.

d2:hasValue( 'hemoglobin' )

Example: where #{hemoglobinPrevious} is set to source type Data element from previous event . The following function call with evaluate whether there exists a value for the hemoglobin among the events preceding the current event.

d2:hasValue( 'hemoglobinPrevious' )
Possible operators to use in a program rule expression
Operator Description

+

Add numbers together

-

Subtract numbers from each other

*

Multiply two numbers

/

Divide two numbers

%

The modulus of two numbers

&&

Logical AND. True only when the expression on the left and right side is true. The left and right side can be yes/no, yes only or a subexpression in parenthesis.

||

Logical OR. True when either the expression on the left or the expression on the right side is true. The left and right side can be yes/no, yes only or a subexpression in parenthesis.

>

Left number greater than right number

>=

Left number greater than or equal to right number

<

Left number less than right number

<=

Left number less than or equal to right number.

==

Left side equal to right side. Supports numbers, text, yes/no and yes only.

!=

Left side not equal to right side. Supports numbers, text, yes/no and yes only.

!

Negates the following value. Can be used for yes/no, yes only or a sub-expression in parenthesis.

()

Parenthesis is used to group sub-expressions.

Custom functions to use in a program rule expression
Function Arguments Description
d2:ceil (number) Rounds the input argument up to the nearest whole number.

Example:

d2:ceil(#{hemoglobinValue})
d2:floor (number) Rounds the input argument down to the nearest whole number.

An example producing the number of weeks the woman is pregnant. Notice that the subexpression #{gestationalAgeDays}/7 is evaluated before the floor function is executed:

d2:floor(#{gestationalAgeDays}/7)
d2:round (number) Rounds the input argument to the nearest whole number.
d2:modulus (number,number) Produces the modulus when dividing the first with the second argument.

An example producing the number of days the woman is into her current pregnancy week:

d2:modulus(#{gestationalAgeDays},7)
d2:zing (number) Evaluates the argument of type number to zero if the value is negative, otherwise to the value itself.
d2:oizp (number) Evaluates the argument of type number to one if the value is zero or positive, otherwise to zero.
d2:concatenate (object, [,object, object,…]) Produces a string concatenated string from the input parameters. Supports any number of parameters. Will mainly be in use in future action types, for example to display gestational age with d2:concatenate(‘weeks’,‘+’,‘gestationalageDays’).
d2:daysBetween (date, date) Produces the number of days between the first and second argument. If the second argument date is before the first argument the return value will be the negative number of days between the two dates. The static date format is ‘yyyy-MM-dd’.

Example, calculating the gestational age(in days) of a woman, based on the last menstrual period and the current event date:

d2:daysBetween(#{lastMenstrualDate},V{event_date})
d2:weeksBetween (date, date) Produces the number of full weeks between the first and second argument. If the second argument date is before the first argument the return value will be the negative number of weeks between the two dates. The static date format is ‘yyyy-MM-dd’.
d2:monthsBetween (date, date) Produces the number of full months between the first and second argument. If the second argument date is before the first argument the return value will be the negative number of months between the two dates. The static date format is ‘yyyy-MM-dd’.
d2:yearsBetween (date, date) Produces the number of years between the first and second argument. If the second argument date is before the first argument the return value will be the negative number of years between the two dates. The static date format is ‘yyyy-MM-dd’.
d2:addDays (date, number) Produces a date based on the first argument date, adding the second argument number of days.

An example calculating the pregnancy due date based on the last menstrual period:

d2:addDays(#{lastMenstrualDate},283)
d2:count (sourcefield) Counts the number of values that is entered for the source field in the argument. The source field parameter is the name of one of the defined source fields in the program - see example

Example usage where #{previousPregnancyOutcome} is one of the source fields in a repeatable program stage “previous pregnancy”:

d2:count('previousPregnancyOutcome')
d2:countIfValue (sourcefield,text) Counts the number of matching values that is entered for the source field in the first argument. Only occurrences that matches the second argument is counted. The source field parameter is the name of one of the defined source fields in the program - see example.

Example usage where #{previousPregnancyOutcome} is one of the source fields in a repeatable program stage “previous pregnancy”. The following function will produce the number of previous pregnancies that ended with abortion:

d2:countIfValue('previousPregnancyOutcome','Abortion')
                                    
d2:countIfZeroPos (sourcefield) Counts the number of values that is zero or positive entered for the source field in the argument. The source field parameter is the name of one of the defined source fields in the program - see example.

Example usage where #{fundalHeightDiscrepancy} is one of the source fields in program, and it can be either positive or negative. The following function will produce the number of positive occurrences:

d2:countIfZeroPos('fundalHeightDiscrepancy')
                                    
d2:hasValue (sourcefield) Evaluates to true of the argument source field contains a value, false if no value is entered.

Example usage, to find if the source field #{currentPregnancyOutcome} is yet filled in:

d2:hasValue('currentPregnancyOutcome')
                                    
d2:zpvc (object, [,object, object,…]) Returns the number of numeric zero and positive values among the given object arguments. Can be provided with any number of arguments.
d2:validatePattern (text, regex-pattern) Evaluates to true if the input text is an exact match with the supplied regular expression pattern. The regular expression needs to be escaped.

Example expression, triggering actions if a number is not on the pattern 9999/99/9:

!d2:validatePattern(A{nrc},'\\d{6}\/\\d{2}\/\\d')

Example expression, triggering actions that if the address is not consisting of letters or white spaces, then a white space, then a number:

!d2:validatePattern(A{registrationAddress},'[\\w ]+ \\d+')

Example, triggering actions if a name contains any numbers:

!d2:validatePattern(A{name},'[^\\d]*')

Example expression, triggering actions if a mobile number contains the illegal number sequence 555:

d2:validatePattern(A{mobile} ,'.*555.*')
d2:left (text, num-chars) Evaluates to the left part of a text, num-chars from the first character.

The text can be quoted or evaluated from a variable:

d2:left(#{variableWithText}, 3)
d2:right (text, num-chars) Evaluates to the right part of a text, num-chars from the last character.

The text can be quoted or evaluated from a variable:

d2:right(#{variableWithText}, 2)
d2:substring (text, start-char-num, end-char-num) Evaluates to the part of a string specified by the start and end character number.

Example expression:

d2:substring(#{variableWithText}, 1, 3)
If the #{variableWithText} in the above example was ‘ABCD’, then the result of the evaluation would be ‘BC’
d2:split (text, delimiter, element-num) Split the text by delimiter, and keep the nth element(0 is the first).

The text can be quoted or evaluated from a variable, the delimiter must be quoted:

d2:split(#{variableWithText}, '-', 1)

Note: comma delimiter(,) is not supported.

d2:length (text) Find the length of a string.

Example:

d2:length(#{variableWithText})
Standard variables to use in program rule expressions
Variable Type Description
V{current_date} (date) Contains the current date whenever the rule is executed.

Example expression:

d2:daysBetween(#{symptomDate},V{current_date}) < 0 
V{event_date} (date) Contains the event date of the current event execution. Will not have a value at the moment the rule is executed as part of the registration form.
V{due_date} (date) This variable will contain the current date when the rule is executed. Note: This means that the rule might produce different results at different times, even if nothing else has changed.
V{event_count} (number) Contains the total number of events in the enrollment.
V{enrollment_date} (date) Contains the enrollment date of the current enrollment. Will not have a value for single event programs.
V{incident_date} (date) Contains the incident date of the current enrollment. Will not have a value for single event programs.
V{enrollment_id} (string) Universial identifier string(UID) of the current enrollment. Will not have a value for single event programs.
V{event_id} (string) Universial identifier string(UID) of the current event context. Will not have a value at the moment the rule is executed as part of the registration form.
V{orgunit_code} (string) Contains the code of the orgunit that is linked to the current enrollment. For single event programs the code from the current event orgunit will be used instead.

Example expression to check wether orgunit code starts with WB_:

d2:left(V{orgunit_code},3) == 'WB_'