Business Rule How To Examples

  • How do I set the Assigned To of the issue to the person updating the issue, if the current value is null?

    if (ASSIGNED_TO={null} && USER.{is internal}) { ASSIGNED_TO = USER; }
     

  • How do I set the value of a field on the add screen?

    if (AREA=Issues && PROJECT=Issues && SCREEN_NAME='ADD')
      {FIELD_NAME=VALUE;}

     

  • How do I set the value of a field on the edit screen?

    if (AREA=Issues && PROJECT=Issues && SCREEN_NAME=EDIT)
      {FIELD_NAME=VALUE;}

     

  • How do I set the value of a field without any conditions?

    FIELD_NAME=VALUE;

    Note that this construct does not work within an onchange rule
     

  • How do I set the value of a field within an onchange rule?

    if (FIELD_NAME.{changed}) {
        OTHER_FIELD = FIELD_NAME;
    }

     

  • How do I set the value of a user field such as ASSIGNED_TO to the current user’s name?

    if (AREA="Contracts" && SCREEN_NAME='ADD') {
      ASSIGNED_TO=USER;
    }

     

  • How do I check to see if the current user is the user assigned to the current issue?

    if (AREA = 'Issues' && USER = ASSIGNED_TO) {
      IS_MANAGER='Y';
    }

     

  • How do I add multiple values with one rule to a multi-valued list field?

    if (AREA = 'Requests' && BUS_UNIT.{CHANGED TO:'ABC'}){
      ASSIGNED_USRS =[PCOLLINS,MGREEN];
    }

     

  • How do I check to see if a value is selected in a multi-valued list?

    if (MY_LIST.{contains 'Yellow'}) { COLOR = 'Yellow';}
     

  • How do I check to see if several values are selected in a multi-valued list?

    if (MY_LIST.{contains 'Yellow', 'Blue', 'Orange'}) {
      COLOR = 'Yellow';
    }

     

  • How do I check to see if a multi-valued list contains some values, but does not contain some other values?

    if (MY_LIST.{contains 'Yellow', 'Green'} && MY_LIST.{excludes 'Blue', 'Red', 'Purple'}) {
      COLOR = 'Yellow';
    }

     

  • How do I check whether the current user has the Administrator role to allow an operation?

    if (AREA='Bugs' && STATUS.{changed_to:'Closed'} && USER_ROLE='Administrator')
      {COMMENTS='OK!'};

     

  • How do I alter a value, if another value has changed?

    if (STATUS.{changed}) {FIELD_X='Changed'};
     

  • How do I set the values of fields to values from the user’s personal options?

    if (AREA='Issues' && SCREEN_NAME='ADD'){
      PHS_COMPANY_NAME = USER.{company name};
      PHS_FIRST_NAME = USER.{first name};
      PHS_LAST_NAME = USER.{last name};
      PHS_JOB_TITLE = USER.{job title};
      PHS_ADDRESS = USER.{address};
      PHS_WORK_PHONE = USER.{work phone};
      PHS_EMAIL = USER.{email};
      PHS_USER_DEFINED_1 = USER.{user defined 1};
    }

     

  • When the Status field first changes its value from Open to Fixed, how do I set the UDF field titled Date First Fixed to the current date:

    if (STATUS.{changed_to:Fixed} && STATUS.{changed_from:Open} && DATE_FIRST_FIXED.{is null} ) {
       DATE_FIRST_FIXED = SYSDATE;
    }

     

  • How do I add two values named UNIT_PRICE and TAX together and put the results in a field named TOTAL_PRICE?

    if (AREA='Bug' && UNIT_PRICE.{not null} && TAX.{not null}){
      TOTAL_PRICE = UNIT_PRICE;   TOTAL_PRICE += TAX;
    }

     

  • How do I add subtract a value named DISCOUNT from a field called PRICE and put the results in a field named DISC_PRICE?

    if (AREA='Issues' && DISCOUNT.{not null} ){
      DISC_PRICE = PRICE;   DISC_PRICE -= DISCOUNT;
    }

  • How do I multiply two values named HOURS and AMOUNT together and put the results in a field named PRICE?

    if (AREA='Customer Issues' && HOURS.{not null} ){
      PRICE = AMOUNT;   PRICE *= HOURS;
    }

     

  • How do I divide a value named TOTAL_COST by a value of HOURS_WORKED and put the results in a field named PRICE_PER_HOUR?

    if (AREA='Issues' && HOURS_WORKED.{not null} ){
      PRICE_PER_HOUR = TOTAL_COST;
      PRICE_PER_HOUR /= HOURS_WORKED;
    }

     

  • How do I make the Comments field required, when the Status changes to Fixed? At the same time, inform the user of their error if they do not provide a Comment (database only rule):

    if (STATUS.{changed_to:Fixed} && STATUS.{changed_from:Open} && COMMENTS.{is null} )
      {Error: Comments are required when an issue is marked fixed.};

     

  • How do I build a text field from other text fields?

    if (AREA="Customers" && SCREEN_NAME='ADD') {
      SHORT_DESCR="New Customer - ";
      SHORT_DESCR&=CUST_NAME;
      SHORT_DESCR&=" - ";
      SHORT_DESCR&=CUST_LEGAL_INDENTITY;
    }

     

  • How do I set the value of a date field to the current date?

    if (AREA='Issues' && ACT_PERCENT_COMPLETE.{changed}) {
      COMPLETE_AS_OF_DATE = {SYSDATE};
    }

     

  • How do I increment a date field?

    NEXT_MAINTENANCE_DATE = MAINTENANCE_COMPLETION_DATE;
    NEXT_MAINTENANCE_DATE += MAINTENANCE_INTERVAL;

     

  • How do I set the value of a field based upon a button being pressed?

    if (AREA=Reviews && ADD_EXPENSE_BTN.{changed})   
      {EXPENSE_ADD='Y';} }

     

  • How do I pop up an error message?

    if (AREA=Issues && SEVERITY_LEVEL=1 && STATUS=Pending)
      {     ERROR: Invalid status with this severity level   }

     

  • How do I set the value of a field to the value of a linked issue field?

    if (AREA='Contracts' && CUST_LIST.{not null}) {
      RELATIONSHIP_GROUP_PARENT = (customerLink).ID;
    }

     

  • How do I "roll-up" the values in repeating rows, so that the main issue represents a concensus of all the repeating row values? A commonly-defined use case for this rule is a scenario where you have a STATUS field on the main issue, which represents the RELEASE_STATUS values held in mulitple repeating rows where each row may have the same or different values.

    For example, let's say that your STATUS and RELEASE_STATUS fields have four values, New, Open, Fixed and Closed. You want the STATUS field to show the value that corresponds to the earliest one in the list that is encountered across al the RELEASE_STATUS values. Thus, if there are three repeating rows, with values of Open, Fixed and Fixed, you want the STATUS field to indicate a "roll-up" value of Open. Likewise, if all three values of RELEASE_STATUS are Open, then you want the STATUS to also show Open. This is achieved with the following onchange rules:

    # First, push our changed status to the STATUS field, so we can then trigger a reset
    # based on all repeating row fields, not simply the one that changed
    if (RELEASE_STATUS.{changed}) {
      STATUS = RELEASE_STATUS;
    }
    # Now do the actual roll up by resetting the main status based on whether specific
    # RELEASE_STATUS values exist. Note that the order of these rules is critical
    if (RELEASE_STATUS.{changed} && RELEASE_STATUS = 'Closed') {
      STATUS = 'Closed';
    }
    if (RELEASE_STATUS.{changed} && RELEASE_STATUS = 'Fixed') {
      STATUS = 'Fixed';
    }
    if (RELEASE_STATUS.{changed} && RELEASE_STATUS = 'Open') {
      STATUS = 'Open';
    }
    if (RELEASE_STATUS.{changed} && RELEASE_STATUS = 'New') {
      STATUS = 'New';
    }

     

  • How can I add a number of blank repeating rows when I first display an add screen? There is no rule action that allows the addition of a blank repeating row. However, you can use the following technique to simulate this, in the following way:
    • Say you want to add 3 blank rows to the repeating row named MY_REPEATING_ROW
    • Create a new text field that is not going to be used on the layout, say MY_HIDDEN_FIELD. This will not have any value associated with it
    • You will use a field on the repeating row layout to store the MY_HIDDEN_FIELD value - remember this is null. Let's say the field on the layout is a text field named MY_RR_FIELD
    • Now use the ADD ROW action to add 3 new rows:
       
      if (SCREEN_NAME = 'ADD') {
        {ADD ROW to MY_REPEATING_ROW MY_RR_FIELD = MY_HIDDEN_FIELD}
        {ADD ROW to MY_REPEATING_ROW MY_RR_FIELD = MY_HIDDEN_FIELD}
        {ADD ROW to MY_REPEATING_ROW MY_RR_FIELD = MY_HIDDEN_FIELD}
      }
       
  • How do I "roll-up" the values in sibling related issues, so that they update the status of their parent issue to Closed, when all the statuses of the child issues change to Closed. This is a common requirement, where a parent issue reflects the status of several or many child issues. The child issues are in a sibling relationship to the parent. The following example can be expanded to provide a roll-up over many different status values, and the same technique can be used to update any other field on the parent issue, using a common value over many child issues. To achieve this structure, consider the following postupdate directive rules:

    # Define a link to the parent issue
    <== link myParent ==>
    RG(RG_NAME = relatedChildren, RG_TYPE = PARENTS)
    # Now define a link for the child issues of the same parent - i.e. the SIBLINGS
    <== link openChildren ==>
    RG(RG_NAME = relatedChildren, RG_TYPE = SIBLINGS), STATUS != 'Closed'
    <== postupdate ==>
    # If we have a parent and all its children are Closed - i.e. there are no children that are not closed
    if (STATUS.{changed to: 'Closed'} && (myParent).ID.{is not null} && (openChildren).ID.{is null}) {
      {UPDATE: myParent STATUS = 'Closed'};
    }

     

  • How do I add a value entered into one field to become a member of a list in another field?

    First define the object to be used to move the value from a text field to a list field:

    <== object cust ==> AREA='Customers', LINK=CUST_LIST, TITLE=CUSTOMER, PRIVACY=false

    Now, use the rule in a way that is similar to:

    if (CUST_LIST.{changed} && AREA=’Issues’) {
      CUST_CONTACT = (cust).CUST_CONTACT;
      EMAIL_ADDRESS = (cust).EMAIL_ADDRESS;
    }

     

  • How do I handle multi-valued fields?

    if (AGENCY.{contains 'Federal'})
      {GROUP = 'Fed';}

     

  • How do I check if a field has a value of null?

    if (AREA=Issues && THEME={null})
      { DRAFT=Y }

     

  • How do I check if a field does not have a value of null?

    if (AREA=Issues && THEME={not null})
      { DRAFT=N }

     

  • How do I create an email action that sends a specific email template I have generated, to a user depending upon a condition when I update an issue?

    <== preupdate ==>
    if (AREA=Issues && STATUS.{changed_to:Pending Approval}) {
      {MAIL:'Issue Approval Request', APPROVER} };

     

  • How do I create an email directive to send the standard notification email to all the users in a role?

    <== mail ==>
    if (AREA="Contracts" && STATUS.{changed to:Finished}) {
      ROLE:MANAGER;
    }

     

  • How do I send standard notification email to the ORIGINATOR, all users in a role and to specific users?

    <== mail ==>
    if (AREA='Trouble Report' && SCREEN_NAME=’ADD’) {
      ROLE:CE;   
      ORIGINATOR;
      JLACEY;
      KMORRIS;
      SCHRISTIANI;
      PREEVES;
      BKISER;
      LMJAMES;
    }

     

  • How do I add a new record based upon a user pressing a button on a screen?

    if (ADD_SERIAL_BTN.{changed} && UNIT_SERIAL.{not null}) {
      { ADD: AREA='Calibration',
             PROJECT='Unit',
             UNIT_SERIAL,
             COMPONENT,
             SITE,
             FACILITY
      };
    }

     

  • How do I update existing records based upon a field on the current screen changing?

    if (CALIB_DATE.{changed} && CALIB_DATE > (unitLink).CALIB_DATE && AREA='Calibration') {
      {UPDATE: unitLink, CALIB_DATE, UNIT_CAL_EXPIRES };
    }

     

  • How do I add a related issue record to the database, following the creation of an issue? This example also shows some other useful techniques. This rule would be executed in the <== postupdate ==> section of the rules. Note the use of the “if” condition to prevent recursion after the new record is added and when the rule fires again for the record just added. Next note the technique where the SHORT_DESCR of the issue is modified before it is added to the new record. The relationship between the records is created by assigning the value of the ID of the current issue to the field named MY_PARENT_ID, which will exist within the add and edit screens of the destination Business Area / Project.

    if (AREA='Helpdesk' && EMPLOYEE_NAME.{not null} && SCREEN_NAME='ADD' && STATUS='New') {
      SHORT_DESCR = 'Install new computer for - ';
      SHORT_DESCR &= EMPLOYEE_NAME;
      {ADD: AREA,
            PROJECT,
            MY_PARENT_ID = ID,
            ASSIGNED_TO = 'BSMITH',
            STATUS = 'Open',
            PRIORITY = 'P 3',
            IT_SELECT_TABS = 'New Employee',
            SHORT_DESCR,
            IT_DATE_REQUESTED,
            IT_APPROVED_BY,
            ORIGINATOR,
            EMPLOYEE_NAME,
            EMPLOYEE_DEPT,
            EMPLOYEE_START_DATE
      };
    }

     

  • How do I only allow the person in the ASSIGNED_TO field have update permission to an issue?

    This is achieved by altering the current role of the user, if that user is not the ASSIGNED_TO. Given that the Guest user is typically not allowed to update issues, then changing the role to that of the Guest or the role identified by the behavior setting LIMITED_USER_ROLE, will cause the record to appear in read-only mode if the user is not the ASSIGNED_TO.

    if (USER != ASSIGNED_TO) USER_ROLE = Guest;
     

  • How can I use a link in a relationship group to detect no Open sub-issues?

    <= link rgOpen ==> RG(RG_NAME=MY_GROUP, RG_TYPE=CHILDREN), STATUS != Closed
    if (STATUS.{changed to: Closed} && (rgOpen).ID.{is not null} )
      {ERROR: Cannot set the status to Closed when there are open child issues.};

     

  • How can I calculate one number as a percentage of another, and display the result with two decimal points?

    If you simply have two rules that state the following:

    TOT_PERCENT_DEFECT = DEFECTS;
    TOT_PERCENT_DEFECT /= SAMPLE_SIZE;

    where the value for DEFECTS is 25, and the value for SAMPLE_SIZE is 100, the result returned is .2, not .25. The reason for this result is that rules try to make sense of operations, especially division, and therefore avoids results like 1.333333333336, and returns 1.3 instead. The rules engine looks at the number of decimal places (the precision) of each of the values, and then limits the number of decimal places returned to no more than the number of decimal places used to express the value, plus the minimum additional needed to get a non-zero value. Generally this works well, but as seen in this case there can be display problems, not the least of which is that there is no way to guarantee that either of the numbers has a certain number of decimal places.

    To avoid this, write the rules as follows:

    TOT_PERCENT_DEFECT = DEFECTS;
    # multiply by 100 first to preserve accuracy
    TOT_PERCENT_DEFECT *=100;
    TOT_PERCENT_DEFECT /= SAMPLE_SIZE;
    # explicitly add '.00' to preserve 2 digits of precision in the result
    TOT_PERCENT_DEFECT /= 100.00;

    By first multiplying by 100, you guarantee that there will be an integer value, and then by specifying the .00 when scaling it back causes the rules to keep at least two digits of precision
     

  • How can I test an incoming email, uploaded with the EVMail utility to see if it is a new or an existing issue?

    if (SHORT_DESCR.{like : 'RE: Extraview [*]*'} )
      { STATUS = "Response received";}

    This rule processes the issue and looks to see if the incoming issue matches the string ‘RE: Extraview [*]*’ (excluding the outermost quotations. The * is a wildcard. If the SHORT_DESC field in the issue contains a value similar to ‘RE: Extraview [#223456] This is a report of a problem.’ then the STATUS of the issue is set to the value of ‘Response received’
     

  • How can I set the Assigned To field of an issue to the value of the owner of a specific user defined field?

    if (CUST_LIST.{changed}) ASSIGNED_TO = CUST_LIST.{owner};

    This onchange rule will look for the owner of the user defined field named CUST_LIST and set this user's ID into the issue as the Assigned To
     

  • How can I ensure that a user enters a date that is in the future, not the past?

    First, create a user defined field in the data dictionary. This is used to hold the number of days different between a date (or day) field, and the current date. The field does not need to be on any layout, but it should have read and write permission. For this example, the field is DIFF_DAYS. The following preupdate rule will check that the date is not in the past.

    if (PROJECT = 'Action' && DATE_FOLLOW_UP.{not null})   {
       DIFF_DAYS = (DATE_FOLLOW_UP - SYSDAY);
    }
    if (PROJECT = 'Action' && DATE_FOLLOW_UP.{not null} && DIFF_DAYS < 0)   
      { STOP: The Follow Up Date must be greater than todays date };

     

  • How can I add new repeating rows and populate them with values?

    The following onchange rule will populate the first blank repeating row, and add two new repeating rows, when the user clicks the button named GENERATE_PARTS_LIST_BTN and the value of the field named ASSEMBLY has a value of Primary.

    if (GENERATE_PARTS_LIST_BTN.{changed} && ASSEMBLY='Primary' ) {
      PARTS='Part 1';
      { ADD ROW: PARTS='Part 2'};
      { ADD ROW: PARTS='Part 3'}; }

    If you want to set additional values on the repeating rows, you can modify the above along these lines:

    if (GENERATE_PARTS_LIST_BTN.{changed} && ASSEMBLY='Primary' ) {
      PARTS='Part 1', RELEASE_STATUS='New';
      { ADD ROW: PARTS='Part 2', RELEASE_STATUS='New'};
      { ADD ROW: PARTS='Part 3', RELEASE_STATUS='New'};
    }

  • How can I set field values, based on the user's choice, when clicking on a navigation bar item?

    The following load rule will work on an Add screen only, and will set values on the screen as it is loaded.

    if (SCREEN_NAME = 'ADD' && MY_ADD_NAV_BUTTON= 'Add Task' ) {
      PRIORITY = 'P 2';
      CATEGORY = 'Task';
    }

    If the user chooses the Add Task navigation bar item, then the PRIORITY and CATEGORY fields are set as shown above.