Note that this construct does not work within an onchange rule
if (FIELD_NAME.{changed}) OTHER_FIELD = FIELD_NAME
if (AREA = 'Issues' && USER = ASSIGNED_TO) {
IS_MANAGER='Y'; }
if (AREA = 'Requests' && BUS_UNIT.{CHANGED TO:'ABC'}){
ASSIGNED_TO =[PCOLLINS,MGREEN];}
If (MY_LIST.{contains 'Yellow'}) {
COLOR = 'Yellow';}
If (MY_LIST.{contains 'Yellow', 'Blue', 'Orange'}) {
COLOR = 'Yellow';}
If (MY_LIST.{contains 'Yellow', 'Green'} && MY_LIST.{excludes 'Blue', 'Red', 'Purple'}) {
COLOR = 'Yellow';}
if (STATUS.{changed_to:Fixed} && STATUS.{changed_from:Open} && DATE_FIRST_FIXED.{is null} )
DATE_FIRST_FIXED = SYSDATE;
if (AREA='Bug' && UNIT_PRICE.{not null} && TAX.{not null}){
TOTAL_PRICE = UNIT_PRICE;
TOTAL_PRICE += TAX;
}
if (AREA='Issues' && DISCOUNT.{not null} ){
DISC_PRICE = PRICE;
DISC_PRICE -= DISCOUNT;
}
if (AREA='Customer Issues' && HOURS.{not null} ){
PRICE = AMOUNT;
PRICE *= HOURS;
}
if (AREA='Issues' && HOURS_WORKED.{not null} ){
PRICE_PER_HOUR = TOTAL_COST;
PRICE_PER_HOUR /= HOURS_WORKED;
}
if (STATUS.{changed_to:Fixed} && STATUS.{changed_from:Open} && COMMENTS.{is null} )
{Error: Comments are required when an issue is marked fixed.};
if (AREA="Customers" && SCREEN_NAME='ADD') {
SHORT_DESCR="New Customer - ";
SHORT_DESCR&=CUST_NAME;
SHORT_DESCR&=" - ";
SHORT_DESCR&=CUST_LEGAL_INDENTITY;
}
NEXT_MAINTENANCE_DATE = MAINTENANCE_COMPLETION_DATE;
NEXT_MAINTENANCE_DATE += MAINTENANCE_INTERVAL;
if (AREA=Reviews && ADD_EXPENSE_BTN.{changed})
{EXPENSE_ADD='Y';}
}
if (AREA=Issues && SEVERITY_LEVEL=1 && STATUS=Pending)
{
ERROR: Invalid status with this severity level
}
if (AREA='Contracts' && CUST_LIST.{not null}) {
RELATIONSHIP_GROUP_PARENT = (customerLink).ID;
}
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'; }
# 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'
# 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'};
}
<== 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;
}
if (AGENCY.{contains 'Federal'})
{GROUP = 'Fed';}
if (AREA=Issues && THEME={null})
{ DRAFT=Y }
if (AREA=Issues && THEME={not null})
{ DRAFT=N }
if (AREA=Issues && STATUS.{changed_to:Pending Approval}) {
{MAIL:'Issue Approval Request', APPROVER} };
if (AREA='Trouble Report' && SCREEN_NAME=’ADD’) {
ROLE:CE;
ORIGINATOR;
JLACEY;
KMORRIS;
SCHRISTIANI;
PREEVES;
BKISER;
LMJAMES;
}
if (ADD_SERIAL_BTN.{changed} && UNIT_SERIAL.{not null}) {
{ADD: AREA='Calibration',
PROJECT='Unit',
UNIT_SERIAL,
COMPONENT,
SITE,
FACILITY};
}
if (CALIB_DATE.{changed} && CALIB_DATE > (unitLink).CALIB_DATE && AREA='Calibration') {
{UPDATE: unitLink, CALIB_DATE, UNIT_CAL_EXPIRES };
}
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 };
}
if (USER != ASSIGNED_TO) USER_ROLE = Guest;
<= 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.};
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.
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’.
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
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
{ STOP: The Follow Up Date must be greater than todays date };
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'};
}