Skip to main content

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 equal
  • IS EMPTY Field has no value
  • IS NOT EMPTY Field has a value
  • IN Matches any value in list
  • NOT IN Doesn't match any value in list
  • CONTAINS String contains substring
  • DOES NOT CONTAIN String doesn't contain substring

Examples:

Simple Comparison:

{amount} > 5000

String Comparison:

{status} = 'Pending Approval'

Multiple Values:

{custbody_order_type} IN ('Rush', 'Expedited', 'Emergency')

Date Comparison:

{shipdate} < {today}

Empty Check:

{memo} IS EMPTY

Formula (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 true
  • OR - At least one condition must be true
  • NOT - Inverts condition

Examples:

Complex Logic:

{amount} > 5000 AND {entity.custentity_credit_status} = 'Approved'

Multiple Conditions:

({status} = 'Pending Approval' OR {status} = 'Pending Review') AND {amount} > 10000

Date Calculations:

{shipdate} - {trandate} < 2

String 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} * 100

Weighted 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' END

String 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 Manager

Multiple 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 = Approved

User Condition#

Check if specific user is current user.

Configuration:

  • Select user(s)
  • Can check multiple users

Examples:

Specific User:

Current User is John Smith

Multiple 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 EMPTY

Location Fields:

{location.custrecord_warehouse_capacity} > 1000

Item 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} <= 10000

NOT 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} <= 10000

Outside Range:

{amount} < 5000 OR {amount} > 10000

Multiple Ranges:

Tier 1: {amount} >= 0 AND {amount} < 1000Tier 2: {amount} >= 1000 AND {amount} < 5000  Tier 3: {amount} >= 5000 AND {amount} < 10000Tier 4: {amount} >= 10000

Date-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} > 30

Business Days:

ROUND(({duedate} - {trandate}) * 5/7, 0) > 10

Relative Dates:

{shipdate} <= {today} + 7

String 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 EMPTY

Is Not Empty:

{purchaseorder} IS NOT EMPTY

Has Value:

LENGTH({custbody_notes}) > 0

No 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}) < 100

FLOOR/CEILING:

FLOOR({quantity} / {item.custitem_case_qty})

MOD (Modulo):

MOD({tranid}, 2) = 0  // Even transaction numbers

String Functions#

LENGTH:

LENGTH({memo}) > 100

SUBSTR:

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}) > 12

ADD_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) > 0

DECODE:

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} > 5

Testing Conditions#

Test Strategy#

Create Test Cases:

  1. Condition should be TRUE
  2. Condition should be FALSE
  3. Boundary values
  4. Edge cases
  5. Null/empty values

Example Test Cases for: {amount} > 5000

Test CaseAmountExpected Result
Normal - TRUE10000TRUE
Normal - FALSE3000FALSE
Boundary - At limit5000FALSE
Boundary - Just over5001TRUE
Edge - Zero0FALSE
Edge - Negative-1000FALSE
Edge - EmptynullFALSE

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 scenarios

Ignoring Null Values:

Bad: Assume fields always have valuesGood: Test with empty/null fields

Not Testing Boundaries:

Bad: Test 100 and 10000 for {amount} > 5000Good: Also test 5000, 5001, 4999

Best 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 conditions

Use 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} > threshold

Avoid 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 fields

Minimize 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} > 100

Maintainability#

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 formats

Avoid 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} <= 5000

Risk-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} + 2

Customer 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} > 10

At-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.5

Inventory Management#

Reorder Point:

Trigger Reorder:  {item.quantityavailable} <= {item.custitem_reorder_point}  AND {item.custitem_auto_reorder} = 'T'  AND {item.quantityonorder} = 0

Overstock Alert:

Overstock Warning:  {item.quantityavailable} > {item.custitem_max_stock_level}  AND {item.custitem_days_supply} > 180

Multi-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} > 5000

Check Data Types:

Problem: {custbody_text_amount} > 5000  // Comparing text to numberSolution: TO_NUMBER({custbody_text_amount}) > 5000

Check Null Values:

Problem: {custbody_discount} > 0  // Returns FALSE if nullSolution: NVL({custbody_discount}, 0) > 0

Check 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 logic

Contradiction (Always FALSE):

Problem: {amount} > 5000 AND {amount} < 1000  // ImpossibleSolution: Use OR instead of AND

Operator 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} = 3

Performance 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 checks

Complex String Operations:

Problem:  UPPER(TRIM(REPLACE({entity.companyname}, '-', ''))) LIKE '%CORP%'
Solution:  Create formula field that pre-processes  Or use simpler comparison

Condition 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} <= maximum

Either Field Has Value:

{field1} IS NOT EMPTY OR {field2} IS NOT EMPTY

Both Fields Have Value:

{field1} IS NOT EMPTY AND {field2} IS NOT EMPTY