Workflow Conditions
What are Conditions?#
Conditions are the logic that controls when workflows execute actions and transitions. They're the "IF" part of workflow logic that determines what happens and when.
Where Conditions are Used#
Workflow Level#
Controls if entire workflow initiates
State Level#
Determines which state to enter
Transition Level#
Controls movement between states
Action Level#
Determines if specific action executes
Condition Types#
Field Value Comparison#
Compare a field against a value.
Configuration:
- Field to compare
- Operator (equals, greater than, less than, etc.)
- Value to compare against
Operators:
=Equal to!=Not equal to>Greater than>=Greater than or equal<Less than<=Less than or equalIS EMPTYField has no valueIS NOT EMPTYField has a valueINMatches any value in listNOT INDoesn't match any value in listCONTAINSString contains substringDOES NOT CONTAINString doesn't contain substring
Examples:
Simple Comparison:
{amount} > 5000String Comparison:
{status} = 'Pending Approval'Multiple Values:
{custbody_order_type} IN ('Rush', 'Expedited', 'Emergency')Date Comparison:
{shipdate} < {today}Empty Check:
{memo} IS EMPTYFormula (Boolean)#
Custom formula that returns true or false.
Syntax: Use NetSuite formula syntax with field references in curly braces.
Logical Operators:
AND- All conditions must be trueOR- At least one condition must be trueNOT- Inverts condition
Examples:
Complex Logic:
{amount} > 5000 AND {entity.custentity_credit_status} = 'Approved'Multiple Conditions:
({status} = 'Pending Approval' OR {status} = 'Pending Review') AND {amount} > 10000Date Calculations:
{shipdate} - {trandate} < 2String Operations:
{entity.companyname} LIKE '%Corporation%' AND {entity.custentity_customer_type} = 'Enterprise'Nested Conditions:
(({amount} > 10000 AND {custbody_risk_level} = 'High') OR ({amount} > 50000))AND {approvalstatus} = 'Pending'Compare Two Fields#
Compare values of two fields on the same record.
Use Cases:
- Date comparisons
- Quantity checks
- Price validations
- Status verifications
Examples:
Date Validation:
{shipdate} >= {orderdate}Quantity Check:
{quantitycommitted} <= {quantityavailable}Price Comparison:
{custbody_special_price} < {custbody_list_price}Field Consistency:
{custbody_approval_level} = {entity.custentity_required_approval_level}Formula (Numeric)#
Returns a numeric value for comparison or calculation.
Use Cases:
- Mathematical calculations
- Date arithmetic
- Complex scoring
- Threshold calculations
Examples:
Calculate Days Between Dates:
{today} - {trandate}Percentage Calculation:
({amount} - {custbody_cost}) / {amount} * 100Weighted Score:
({custbody_score_a} * 0.5) + ({custbody_score_b} * 0.3) + ({custbody_score_c} * 0.2)Formula (Text)#
Returns text value for comparison.
Use Cases:
- String manipulation
- Conditional text
- Field concatenation
- Complex lookups
Examples:
Conditional Text:
CASE WHEN {amount} > 10000 THEN 'High' WHEN {amount} > 5000 THEN 'Medium' ELSE 'Low' ENDString Combination:
{entity.companyname} || ' - ' || {tranid}Substring Extraction:
SUBSTR({entity.companyname}, 1, 3)Role Condition#
Check if current user has specific role.
Configuration:
- Select role(s)
- Can check multiple roles
Examples:
Single Role:
Current User's Role is Sales ManagerMultiple Roles:
Current User's Role is in (Administrator, Sales Director, CFO)Use Case: Approval Authority
Transition: Auto-ApproveCondition: Current User's Role is in (Director, VP, C-Level)Action: Set Status = ApprovedUser Condition#
Check if specific user is current user.
Configuration:
- Select user(s)
- Can check multiple users
Examples:
Specific User:
Current User is John SmithMultiple Users:
Current User is in (John Smith, Jane Doe, Bob Johnson)Use Case: Executive Override
Action: Override Credit LimitCondition: Current User is in (CEO, CFO)Comparison with Related Record#
Access fields from related records.
Syntax:
{relatedrecord.fieldname}Examples:
Customer Fields:
{entity.creditlimit} > {entity.balance} + {amount}Sales Rep Fields:
{salesrep.supervisor.email} IS NOT EMPTYLocation Fields:
{location.custrecord_warehouse_capacity} > 1000Item Fields:
{item.custitem_requires_approval} = 'T'Combining Conditions#
AND Logic#
All conditions must be true.
Example: High Value + Premium Customer
{amount} > 10000 AND {entity.custentity_customer_tier} = 'Premium'AND {entity.creditlimit} > {entity.balance}Use Case:
Transition: Fast Track ApprovalConditions (ALL must be true): 1. {amount} < 25000 2. {entity.custentity_credit_status} = 'Excellent' 3. {salesrep.supervisor} IS NOT EMPTY 4. {custbody_rush_order} = 'F'OR Logic (Alternative Paths)#
At least one condition must be true - implement using multiple transitions.
Example: Multiple Approval Paths
Transition 1: Director Approval Condition: {amount} > 50000 Transition 2: Manager Approval Condition: {amount} > 25000 AND {amount} <= 50000 Transition 3: Supervisor Approval Condition: {amount} > 10000 AND {amount} <= 25000 Transition 4: Auto-Approve Condition: {amount} <= 10000NOT Logic#
Invert condition.
Examples:
Using NOT:
NOT ({status} = 'Approved')Using !=:
{status} != 'Approved'Using NOT IN:
{custbody_region} NOT IN ('EMEA', 'APAC')Advanced Condition Patterns#
Threshold Ranges#
Check if value falls within range.
Between Values:
{amount} >= 5000 AND {amount} <= 10000Outside Range:
{amount} < 5000 OR {amount} > 10000Multiple Ranges:
Tier 1: {amount} >= 0 AND {amount} < 1000Tier 2: {amount} >= 1000 AND {amount} < 5000 Tier 3: {amount} >= 5000 AND {amount} < 10000Tier 4: {amount} >= 10000Date-Based Conditions#
Same Day:
{trandate} = {today}Past Dates:
{duedate} < {today}Future Dates:
{shipdate} > {today}Date Range:
{trandate} >= '01/01/2025' AND {trandate} <= '12/31/2025'Days Calculation:
{today} - {trandate} > 30Business Days:
ROUND(({duedate} - {trandate}) * 5/7, 0) > 10Relative Dates:
{shipdate} <= {today} + 7String Matching#
Exact Match:
{entity.companyname} = 'Acme Corporation'Partial Match:
{entity.companyname} LIKE '%Corporation%'Starts With:
{tranid} LIKE 'SO-%'Ends With:
{entity.email} LIKE '%@company.com'Case Insensitive:
UPPER({entity.companyname}) = 'ACME CORPORATION'Multiple Strings:
{entity.companyname} IN ('Acme Corp', 'Beta Inc', 'Gamma LLC')Null and Empty Checks#
Is Empty:
{memo} IS EMPTYIs Not Empty:
{purchaseorder} IS NOT EMPTYHas Value:
LENGTH({custbody_notes}) > 0No Value or Zero:
({amount} IS EMPTY OR {amount} = 0)Complex Business Logic#
Credit Approval:
( {amount} <= {entity.creditlimit} - {entity.balance} AND {entity.custentity_credit_hold} = 'F' AND {entity.custentity_payment_history} IN ('Excellent', 'Good'))OR( {amount} <= 5000 AND {entity.custentity_credit_status} != 'Blocked')Rush Order Handling:
{custbody_rush_order} = 'T'AND {shipdate} - {today} < 2AND {location.custrecord_supports_rush} = 'T'AND ( {entity.custentity_customer_tier} = 'Premium' OR {amount} > 50000)Inventory Availability:
{item.quantityavailable} >= {quantity}AND {item.custitem_reorder_point} < {item.quantityavailable}AND {location.custrecord_can_fulfill} = 'T'Condition Functions#
Mathematical Functions#
ROUND:
ROUND({amount} * 0.1, 2)ABS (Absolute Value):
ABS({amount} - {custbody_expected_amount}) < 100FLOOR/CEILING:
FLOOR({quantity} / {item.custitem_case_qty})MOD (Modulo):
MOD({tranid}, 2) = 0 // Even transaction numbersString Functions#
LENGTH:
LENGTH({memo}) > 100SUBSTR:
SUBSTR({tranid}, 1, 2) = 'SO'UPPER/LOWER:
UPPER({entity.email}) LIKE '%@COMPANY.COM'CONCAT (||):
{entity.firstname} || ' ' || {entity.lastname} = 'John Smith'TRIM:
TRIM({custbody_reference}) = 'REF123'REPLACE:
REPLACE({tranid}, '-', '') = 'SO12345'Date Functions#
TODAY:
{trandate} = {today}NOW:
{custbody_timestamp} < {now}DATE:
{trandate} >= TO_DATE('2025-01-01', 'YYYY-MM-DD')MONTHS_BETWEEN:
MONTHS_BETWEEN({today}, {entity.datecreated}) > 12ADD_MONTHS:
{custbody_renewal_date} = ADD_MONTHS({today}, 12)Conditional Functions#
CASE:
CASE WHEN {amount} > 10000 THEN 'High' WHEN {amount} > 5000 THEN 'Medium' ELSE 'Low'END = 'High'NVL (Null Value):
NVL({custbody_discount}, 0) > 0DECODE:
DECODE({status}, 'A', 'Active', 'I', 'Inactive', 'Unknown') = 'Active'Aggregate Considerations#
Note: Workflows operate on single records, but you can reference summary fields from related records.
Example:
{entity.overduebalance} > 0{entity.unbilledorders} > 5Testing Conditions#
Test Strategy#
Create Test Cases:
- Condition should be TRUE
- Condition should be FALSE
- Boundary values
- Edge cases
- Null/empty values
Example Test Cases for: {amount} > 5000
| Test Case | Amount | Expected Result |
|---|---|---|
| Normal - TRUE | 10000 | TRUE |
| Normal - FALSE | 3000 | FALSE |
| Boundary - At limit | 5000 | FALSE |
| Boundary - Just over | 5001 | TRUE |
| Edge - Zero | 0 | FALSE |
| Edge - Negative | -1000 | FALSE |
| Edge - Empty | null | FALSE |
Debugging Conditions#
Add Debug Fields:
Create custom fields to show condition evaluation:- custbody_debug_amount_check: {amount} > 5000- custbody_debug_credit_check: {entity.creditlimit} > {entity.balance}- custbody_debug_date_check: {shipdate} >= {today}Use Set Field Actions:
Action: Set Field (for debugging)Field: custbody_debug_logValue: Condition checked at {now}: amount={amount}, result={condition}Workflow Execution Log:
- Shows which conditions evaluated
- Displays TRUE/FALSE results
- Critical for troubleshooting
Common Testing Mistakes#
Not Testing FALSE Path:
Bad: Only test when condition is TRUEGood: Test both TRUE and FALSE scenariosIgnoring Null Values:
Bad: Assume fields always have valuesGood: Test with empty/null fieldsNot Testing Boundaries:
Bad: Test 100 and 10000 for {amount} > 5000Good: Also test 5000, 5001, 4999Best Practices#
Condition Design#
Keep It Simple:
Good: {amount} > 5000
Avoid: ((({amount} > 5000 AND {status} = 'A') OR ({amount} > 10000 AND {status} = 'B')) AND NOT ({entity.type} IN ('X','Y','Z') OR {custbody_flag} = 'T'))Break Complex Conditions:
Instead of one complex condition: Create multiple states/transitions Each with simpler conditionsUse Meaningful Comparisons:
Good: {entity.custentity_credit_status} = 'Approved'
Avoid: {entity.custentity_credit_status} = 'A'Performance#
Order Conditions by Cost:
Cheap checks first: {status} = 'Pending' AND {amount} > 5000 AND {entity.custentity_complex_calculation} > thresholdAvoid Expensive Operations:
Avoid: - Complex string operations on every evaluation - Multiple related record lookups - Heavy mathematical calculations
Consider: - Pre-calculate and store in custom field - Use simpler comparisons - Cache lookups in fieldsMinimize Related Record Access:
Less Efficient: {entity.salesrep.supervisor.department.custrecord_value} > 100
More Efficient: Store needed value in customer record custom field {entity.custentity_cached_dept_value} > 100Maintainability#
Document Complex Conditions:
Condition Description: "Check if customer is premium tier, has good credit, and order amount is within available credit limit" Formula: {entity.custentity_tier} = 'Premium' AND {entity.custentity_credit_rating} IN ('A', 'AA', 'AAA') AND {amount} <= ({entity.creditlimit} - {entity.balance})Use Consistent Patterns:
For similar checks across workflows: Use same field references Use same comparison operators Use same value formatsAvoid Magic Numbers:
Bad: {amount} > 5000
Better (with documentation): {amount} > 5000 // Manager approval threshold
Best (use custom field): {amount} > {entity.custentity_approval_threshold}Condition Examples by Use Case#
Approval Workflows#
Amount-Based Approval:
Director Approval Required: {amount} > 50000
Manager Approval Required: {amount} > 10000 AND {amount} <= 50000
Supervisor Approval Required: {amount} > 5000 AND {amount} <= 10000
Auto-Approved: {amount} <= 5000Risk-Based Approval:
High Risk - Director Approval: {entity.custentity_risk_level} = 'High' OR ({amount} > 25000 AND {entity.custentity_credit_rating} NOT IN ('A', 'AA'))
Medium Risk - Manager Approval: {entity.custentity_risk_level} = 'Medium' OR ({amount} > 10000 AND {entity.custentity_credit_rating} = 'B')
Low Risk - Auto Approve: {entity.custentity_risk_level} = 'Low' AND {amount} <= 10000 AND {entity.custentity_credit_rating} IN ('A', 'AA')Order Processing#
Rush Order Qualification:
Qualifies for Rush Processing: {custbody_rush_requested} = 'T' AND {shipdate} - {today} < 3 AND {location.custrecord_supports_rush} = 'T' AND ( {entity.custentity_tier} = 'Premium' OR {salesrep.supervisor} IS NOT EMPTY )Backorder Check:
Place on Backorder: {item.quantityavailable} < {quantity} AND {item.custitem_allow_backorder} = 'T' AND {custbody_backorder_allowed} != 'F' AND {entity.custentity_accepts_backorders} = 'T'Shipping Method Selection:
Overnight Required: {shipdate} <= {today} + 1 OR {custbody_expedite} = 'T'
2-Day Shipping: {shipdate} <= {today} + 2 AND {custbody_expedite} = 'F'
Ground Shipping: {shipdate} > {today} + 2Customer Management#
Credit Hold Check:
Place on Credit Hold: {entity.balance} > {entity.creditlimit} OR {entity.overduebalance} > 0 OR {entity.custentity_payment_issues} > 2 OR {entity.custentity_credit_hold} = 'T'Customer Tier Evaluation:
Upgrade to Premium: {entity.salesreadonly} > 100000 // Last 12 months AND {entity.custentity_orders_count} > 20 AND {entity.custentity_avg_order_value} > 5000
Upgrade to Standard: {entity.salesreadonly} > 25000 AND {entity.custentity_orders_count} > 10At-Risk Customer:
Flag as At Risk: {today} - {entity.lastorderdate} > 90 AND {entity.custentity_previous_yearly_sales} > 50000 AND {entity.salesreadonly} < {entity.custentity_previous_yearly_sales} * 0.5Inventory Management#
Reorder Point:
Trigger Reorder: {item.quantityavailable} <= {item.custitem_reorder_point} AND {item.custitem_auto_reorder} = 'T' AND {item.quantityonorder} = 0Overstock Alert:
Overstock Warning: {item.quantityavailable} > {item.custitem_max_stock_level} AND {item.custitem_days_supply} > 180Multi-Location Check:
Check Alternate Location: {location.quantityavailable} < {quantity} AND {item.custitem_check_alternate_locations} = 'T' AND EXISTS ( SELECT 1 FROM locations l WHERE l.quantityavailable >= {quantity} )Troubleshooting Conditions#
Condition Not Evaluating as Expected#
Check Field References:
Problem: {ammount} > 5000 // Typo in field nameSolution: {amount} > 5000Check Data Types:
Problem: {custbody_text_amount} > 5000 // Comparing text to numberSolution: TO_NUMBER({custbody_text_amount}) > 5000Check Null Values:
Problem: {custbody_discount} > 0 // Returns FALSE if nullSolution: NVL({custbody_discount}, 0) > 0Check Date Formats:
Problem: {trandate} = '01/15/2025' // Format mismatchSolution: {trandate} = TO_DATE('2025-01-15', 'YYYY-MM-DD')Condition Always TRUE or Always FALSE#
Tautology (Always TRUE):
Problem: {amount} > 0 OR {amount} <= 0 // Always trueSolution: Check your logicContradiction (Always FALSE):
Problem: {amount} > 5000 AND {amount} < 1000 // ImpossibleSolution: Use OR instead of ANDOperator Precedence:
Problem: {a} = 1 OR {b} = 2 AND {c} = 3Evaluates as: {a} = 1 OR ({b} = 2 AND {c} = 3)Solution: Use parentheses: ({a} = 1 OR {b} = 2) AND {c} = 3Performance Issues#
Too Many Lookups:
Problem: {entity.salesrep.supervisor.email} IS NOT EMPTY AND {entity.salesrep.supervisor.custentity_approval_limit} > {amount} AND {entity.salesrep.supervisor.department.name} = 'Sales'
Solution: Pre-calculate and store in customer record Or break into multiple simpler checksComplex String Operations:
Problem: UPPER(TRIM(REPLACE({entity.companyname}, '-', ''))) LIKE '%CORP%'
Solution: Create formula field that pre-processes Or use simpler comparisonCondition Cheat Sheet#
Common Patterns#
Value Exists:
{field} IS NOT EMPTYLENGTH({field}) > 0{field} != ''Value Doesn't Exist:
{field} IS EMPTYNVL({field}, '') = ''Date is Today:
{datefield} = {today}Date is in Past:
{datefield} < {today}Date is in Future:
{datefield} > {today}Within Date Range:
{datefield} >= '2025-01-01' AND {datefield} <= '2025-12-31'Field Changed (Before Submit):
{field.new} != {field.old}Multiple Values:
{field} IN ('Value1', 'Value2', 'Value3')Range Check:
{field} >= minimum AND {field} <= maximumEither Field Has Value:
{field1} IS NOT EMPTY OR {field2} IS NOT EMPTYBoth Fields Have Value:
{field1} IS NOT EMPTY AND {field2} IS NOT EMPTY