Scheduled Scripts

Scheduled Scripts (Scheduled Jobs) run Script Modules automatically on a recurring schedule. They are the primary tool for nightly batch processing, automated data maintenance, recurring report generation, and timed integration tasks.

How Scheduled Jobs Work

Scheduled Jobs run at 5:00 AM Eastern Time on their configured schedule. They execute a Script Module in the context of a specific User Account, giving the script the same permissions and account context as that user.

Creating a Scheduled Job

Scheduled Jobs are found on the Integration sidebar.

  1. Go to Integration > Scheduled Jobs.
  2. Click Create New Scheduled Job.
  3. Enter a Name and optional description.
  4. Select the Script Module to run.
  5. Select the User Account the script will run as.
  6. Set the Schedule (see below).
  7. Set the Start Recurrence Date — the first date the job will run.
  8. Ensure Active is checked.
  9. Save.

Schedule Options

Schedule Runs
Daily Every day at 5AM Eastern
Semi-Weekly Twice per week (Monday and Thursday)
Weekly Once per week (Monday)
Bi-Weekly Every two weeks
Monthly First of each month

The Next Recurrence Date field shows when the job will next run. This is updated automatically after each execution.

Variables Available in Scheduled Job Scripts

Variable Content
user The configured User Account the job runs as
account The account associated with that user
log Logger for debug and error output
elProcessor EL evaluation utilities
messages Externalized text
ReferenceData System-wide reference values

Any CDI service can be imported: import "queryService"; import "contactService"; etc.

Common Patterns

Nightly Data Export

import "queryService";
import "commonHttpClient";

// Get all active transactions from the past day
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);

var transactions = queryService.createQuery(
    "select po from PurchaseOrder po where po.account = :account " +
    "and po.status = 'ACTIVE' and po.orderReceived >= :since"
).setParameter('account', account)
 .setParameter('since', yesterday)
 .getResultList();

// Build export payload
var rows = [];
for each (var po in transactions) {
    rows.push({
        id: po.id,
        amount: po.amount,
        contact: po.contact != null ? po.contact.email : '',
        campaign: po.campaign != null ? po.campaign.name : ''
    });
}

// POST to external system
var response = commonHttpClient.post(
    'https://api.example.com/import/transactions',
    JSON.stringify({transactions: rows}),
    'application/json'
);
log.info('Exported ' + rows.length + ' transactions. Response: ' + response);

Nightly Status Update

import "queryService";
import "purchaseOrderService";

// Find pledges past their due date with no payment
var overdue = queryService.createQuery(
    "select po from PurchaseOrder po where po.account = :account " +
    "and po.type = 'PLEDGE' and po.status = 'ACTIVE' " +
    "and po.dueDate < CURRENT_DATE"
).setParameter('account', account).getResultList();

log.info('Found ' + overdue.length + ' overdue pledges');

for each (var po in overdue) {
    var customStatus = po.get('ManualStatus');
    if (customStatus == null || customStatus.value == '') {
        purchaseOrderService.setCustomProperty(po, 'ManualStatus', 'OVERDUE');
        log.info('Marked pledge ' + po.id + ' as OVERDUE');
    }
}

Recurring Report Email

import "mailer";
import "queryService";

// Count this month's new donors
var firstOfMonth = new Date();
firstOfMonth.setDate(1);

var newDonors = queryService.createQuery(
    "select count(distinct po.contact) from PurchaseOrder po " +
    "where po.account = :account and po.status = 'ACTIVE' " +
    "and po.type in ('RECEIVED', 'PLEDGE') and po.orderReceived >= :since"
).setParameter('account', account)
 .setParameter('since', firstOfMonth)
 .getSingleResult();

mailer.sendEmail(
    user.email,
    'Monthly New Donor Count',
    '<p>New donors this month: <strong>' + newDonors + '</strong></p>'
);

Deactivating and Troubleshooting

  • Uncheck Active to pause a Scheduled Job without deleting it.
  • The Last Recurrence Date field shows when the job last ran.
  • If a job fails, the error is logged server-side. Contact help@donorpoint.com to request a log review.
  • Test your script logic manually using the Run button on the Script Module edit page before scheduling it.