Skip to main content

ScriptTask - Inline Code Execution

ScriptTask executes JavaScript/Node.js code directly within the process workflow. It has full access to process variables and can perform calculations, data transformations, and business logic.

Properties

Required Properties

  • Script: The JavaScript code to execute
  • TaskType: Must be "ScriptTask"
  • Name: Display name of the task

Optional Properties

  • ScriptLanguage: Language (default: "javascript")
  • ResultVariable: Variable name to store script result
  • InputMapping: Map process variables to script inputs
  • OutputMapping: Map script outputs to process variables
  • EntityState: State during execution
  • AsyncBefore/AsyncAfter: Async execution flags

BPMN XML Examples

Basic Script Task

<bpmn:scriptTask id="Task_Calculate" name="Calculate Loan Metrics">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Calculate monthly payment
const monthlyRate = annualRate / 12 / 100;
const numPayments = termMonths;

monthlyPayment = loanAmount *
(monthlyRate * Math.pow(1 + monthlyRate, numPayments)) /
(Math.pow(1 + monthlyRate, numPayments) - 1);

totalPayment = monthlyPayment * numPayments;
totalInterest = totalPayment - loanAmount;

console.log('Monthly Payment:', monthlyPayment);
" />
<custom:property name="ScriptLanguage" value="javascript" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_In</bpmn:incoming>
<bpmn:outgoing>Flow_Out</bpmn:outgoing>
</bpmn:scriptTask>

Script with Result Variable

<bpmn:scriptTask id="Task_ComputeScore" name="Calculate Credit Score">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Calculate credit score based on multiple factors
let score = 600; // Base score

// Payment history (35%)
if (onTimePayments > 95) score += 100;
else if (onTimePayments > 80) score += 50;

// Credit utilization (30%)
const utilization = creditUsed / creditLimit * 100;
if (utilization &lt; 30) score += 80;
else if (utilization &lt; 50) score += 40;
else score -= 20;

// Length of credit history (15%)
if (accountAgeMonths > 60) score += 40;
else if (accountAgeMonths > 24) score += 20;

// Cap at 850
score = Math.min(score, 850);

return score;
" />
<custom:property name="ResultVariable" value="creditScore" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>

Script with Input/Output Mapping

<bpmn:scriptTask id="Task_ValidateData" name="Validate Application Data">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Validate input data
const errors = [];

if (!customerName || customerName.trim() === '') {
errors.push('Customer name is required');
}

if (!email || !email.includes('@')) {
errors.push('Valid email is required');
}

if (amount &lt;= 0 || amount > 1000000) {
errors.push('Loan amount must be between $1 and $1,000,000');
}

if (termMonths &lt; 12 || termMonths > 360) {
errors.push('Term must be between 12 and 360 months');
}

// Set validation results
isValid = errors.length === 0;
validationErrors = errors;
validatedAt = new Date().toISOString();
" />

<!-- Map process variables to script inputs -->
<custom:property name="InputMapping" value="{
&quot;customerName&quot;: &quot;application.customerName&quot;,
&quot;email&quot;: &quot;application.email&quot;,
&quot;amount&quot;: &quot;application.loanAmount&quot;,
&quot;termMonths&quot;: &quot;application.term&quot;
}" />

<!-- Map script outputs to process variables -->
<custom:property name="OutputMapping" value="{
&quot;validationResult&quot;: &quot;isValid&quot;,
&quot;validationErrors&quot;: &quot;errors&quot;,
&quot;validationTimestamp&quot;: &quot;validatedAt&quot;
}" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>

Script with BankLingo Commands

<bpmn:scriptTask id="Task_EnrichData" name="Enrich Customer Data">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Use BankLingo commands to fetch additional data

// Get customer details
const customerDetails = doCmd('GetCustomerById', { customerId });
customerName = customerDetails.fullName;
customerSegment = customerDetails.segment;

// Get account balance
const accountInfo = doCmd('GetAccountBalance', {
accountNumber: customerDetails.primaryAccount
});
availableBalance = accountInfo.availableBalance;

// Calculate debt-to-income ratio
const monthlyIncome = customerDetails.monthlyIncome;
const existingDebts = doCmd('GetCustomerDebts', { customerId });
const totalMonthlyDebt = existingDebts.reduce((sum, debt) => sum + debt.monthlyPayment, 0);

debtToIncomeRatio = (totalMonthlyDebt / monthlyIncome) * 100;

// Set risk category
if (debtToIncomeRatio > 43) {
riskCategory = 'High';
} else if (debtToIncomeRatio > 36) {
riskCategory = 'Medium';
} else {
riskCategory = 'Low';
}

console.log('Customer enriched:', customerName, 'Risk:', riskCategory);
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>

Conditional Logic Script

<bpmn:scriptTask id="Task_DetermineApprovalPath" name="Determine Approval Requirements">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Determine which approval path to take based on business rules

let requiredApprovers = [];
let approvalLevel = 'Standard';

// High amount requires senior approval
if (loanAmount > 100000) {
requiredApprovers.push('SeniorOfficer');
approvalLevel = 'Senior';
}

// High risk requires additional approval
if (riskScore > 70 || debtToIncomeRatio > 40) {
requiredApprovers.push('RiskManager');
approvalLevel = 'Enhanced';
}

// New customers need compliance check
if (customerTenureMonths &lt; 12) {
requiredApprovers.push('ComplianceOfficer');
}

// VIP customers get fast track
if (customerSegment === 'VIP' &amp;&amp; loanAmount &lt; 50000) {
requiredApprovers = ['LoanOfficer'];
approvalLevel = 'FastTrack';
}

// Set variables for gateway routing
approvalPath = approvalLevel;
approversNeeded = requiredApprovers.join(',');
estimatedApprovalDays = requiredApprovers.length * 2;
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>

Accessing Process Variables

Scripts have direct access to all process variables:

// Read variables
const amount = loanAmount; // Direct access
const customer = customerData.name; // Nested access

// Set variables
approvalStatus = 'Approved';
processedDate = new Date().toISOString();

// Modify variables
loanAmount = loanAmount * 1.1; // Add 10% fee
customerData.verified = true;

Using BankLingo Commands

Call any BankLingo command using doCmd():

// Execute command
const result = doCmd('CommandName', {
parameter1: value1,
parameter2: value2
});

// Example: Get account balance
const balance = doCmd('GetAccountBalance', {
accountNumber: accountNumber
});
availableBalance = balance.availableBalance;

// Example: Create transaction
const transaction = doCmd('CreateTransaction', {
accountId: accountId,
amount: amount,
type: 'Debit',
description: 'Loan disbursement'
});
transactionId = transaction.id;

Use Cases

1. Data Transformation

Transform data between different formats:

<bpmn:scriptTask id="Task_Transform" name="Transform Data">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Transform customer data from external format to internal format
internalCustomer = {
id: externalData.customer_id,
fullName: externalData.first_name + ' ' + externalData.last_name,
email: externalData.contact.email,
phone: externalData.contact.phone,
address: {
street: externalData.address.street_address,
city: externalData.address.city,
state: externalData.address.state_code,
zip: externalData.address.postal_code
},
dateOfBirth: new Date(externalData.dob).toISOString()
};
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>

2. Complex Calculations

Perform business calculations:

<bpmn:scriptTask id="Task_PricingCalculation" name="Calculate Loan Pricing">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Base rate from market
let interestRate = baseMarketRate;

// Adjust for credit score
if (creditScore &lt; 600) interestRate += 5.0;
else if (creditScore &lt; 650) interestRate += 3.0;
else if (creditScore &lt; 700) interestRate += 1.5;
else if (creditScore >= 750) interestRate -= 0.5;

// Adjust for loan-to-value ratio
const ltvRatio = loanAmount / collateralValue * 100;
if (ltvRatio > 80) interestRate += 1.0;
else if (ltvRatio > 90) interestRate += 2.0;

// Adjust for relationship
if (customerTenureYears > 5) interestRate -= 0.25;
if (numberOfAccounts > 3) interestRate -= 0.15;

// Calculate final numbers
finalInterestRate = Math.max(interestRate, minimumRate);
monthlyPayment = calculatePayment(loanAmount, finalInterestRate, termMonths);
totalInterest = (monthlyPayment * termMonths) - loanAmount;
aprRate = calculateAPR(loanAmount, finalInterestRate, fees, termMonths);
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>

3. Validation

Validate business rules:

<bpmn:scriptTask id="Task_BusinessRules" name="Validate Business Rules">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
const violations = [];

// Rule 1: Debt-to-income ratio
if (debtToIncomeRatio > 43) {
violations.push({
rule: 'DTI_LIMIT',
message: 'Debt-to-income ratio exceeds maximum of 43%',
severity: 'Critical'
});
}

// Rule 2: Minimum credit score
if (creditScore &lt; 580) {
violations.push({
rule: 'MIN_CREDIT_SCORE',
message: 'Credit score below minimum requirement',
severity: 'Critical'
});
}

// Rule 3: Maximum loan amount
const maxLoan = annualIncome * 3;
if (loanAmount > maxLoan) {
violations.push({
rule: 'MAX_LOAN_AMOUNT',
message: 'Loan amount exceeds 3x annual income',
severity: 'High'
});
}

// Rule 4: Recent bankruptcies
if (bankruptcyInLast7Years) {
violations.push({
rule: 'BANKRUPTCY_HISTORY',
message: 'Recent bankruptcy on record',
severity: 'High'
});
}

ruleViolations = violations;
rulesPass = violations.length === 0;
criticalViolations = violations.filter(v => v.severity === 'Critical').length;
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>

4. Decision Logic

Make routing decisions:

<bpmn:scriptTask id="Task_RouteDecision" name="Determine Routing">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Complex routing decision

// Check for auto-approval eligibility
const autoApproveEligible =
creditScore >= 720 &amp;&amp;
debtToIncomeRatio &lt; 36 &amp;&amp;
loanAmount &lt;= 25000 &amp;&amp;
customerTenureMonths >= 24 &amp;&amp;
!recentDelinquencies;

if (autoApproveEligible) {
routingDecision = 'AutoApprove';
return;
}

// Check for auto-rejection
const autoRejectCriteria =
creditScore &lt; 580 ||
debtToIncomeRatio > 50 ||
recentBankruptcy ||
fraudFlagged;

if (autoRejectCriteria) {
routingDecision = 'AutoReject';
rejectionReason = 'Does not meet minimum criteria';
return;
}

// Needs manual review - determine level
if (loanAmount > 100000 || riskScore > 70) {
routingDecision = 'SeniorReview';
} else {
routingDecision = 'StandardReview';
}
" />
<custom:property name="ResultVariable" value="routingDecision" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>

Best Practices

1. Keep Scripts Focused

Each script task should do one thing well:

<!-- Good - Single responsibility -->
<bpmn:scriptTask id="Task_Calculate" name="Calculate Metrics" />
<bpmn:scriptTask id="Task_Validate" name="Validate Results" />

<!-- Avoid - Doing too much -->
<bpmn:scriptTask id="Task_Everything" name="Calculate, Validate, and Route" />

2. Handle Errors

Use try-catch for error handling:

try {
const result = doCmd('SomeCommand', { params });
processedResult = result.data;
} catch (error) {
console.error('Command failed:', error.message);
errorOccurred = true;
errorMessage = error.message;
}

3. Log for Debugging

Use console.log for debugging:

console.log('Starting calculation with amount:', loanAmount);
const result = calculateSomething();
console.log('Calculation result:', result);

4. Use Meaningful Variable Names

// Good
const monthlyPayment = calculatePayment(principal, rate, term);
const annualPercentageRate = calculateAPR(amount, rate, fees);

// Avoid
const mp = calc(p, r, t);
const apr = calcAPR(a, r, f);

5. Comment Complex Logic

// Calculate effective interest rate
// Formula: ((1 + r/n)^n) - 1
// Where r = nominal rate, n = compounding periods
const effectiveRate = Math.pow(1 + (nominalRate / compoundingPeriods), compoundingPeriods) - 1;

Performance Considerations

  • Keep scripts lightweight: Complex calculations should use ServiceTask to call APIs
  • Avoid loops over large datasets: Use BankLingo commands for bulk operations
  • Cache repeated calculations: Store results in variables
  • Use async for long operations: Set AsyncAfter="true" for better performance

Next Steps