React to events and triggers
Use an event to apply actions when a condition becomes true or on selected dates.
import { actions, cashflow, currencies, defineModel, entity, event, inflow, lifecycle, periods, schedule, state } from "deccf";
const active = state("active");
const sold = state("sold");
const propertyLifecycle = lifecycle({
states: [active, sold],
initial: active,
transitions: [{ from: active, to: sold, when: (ctx) => ctx.time.index === 11 }],
});
const property = entity.asset({ lifecycle: propertyLifecycle });
const rent = cashflow({ owner: property, direction: inflow, schedule: schedule.monthly(), amount: 2_000 });
const stopRent = event({
when: (ctx) => ctx.isInState(property, sold),
actions: [actions.deactivate(rent)],
});
const model = defineModel({
name: "stop-rent-on-sale",
currency: currencies.SEK,
timeline: periods.monthly({ from: "2026-01", count: 24 }),
entities: { property },
flows: { rent },
events: { stopRent },
});
return model;An unscheduled condition fires on its false-to-true transition. With schedule, the event checks the condition only in scheduled periods. Supported actions are actions.setState, actions.setField, actions.activate, and actions.deactivate.
An activation action changes whether a cashflow is active for later calculation steps. Events follow the engine's period order; they cannot change periods that have already been calculated.
See the API overview for validation and calculation order.
Schedule a flow after another flow
Use trigger() when a cashflow should start a delayed booking. Each account has its own type and category. Here, half the rent is booked to cash and half to receivables. After 30 days, the receivable is settled into cash.
import { account, cashflow, category, currencies, defineModel, entity, periods, schedule, trigger } from "deccf";
const anna = entity.party();
const cash = account({ owner: anna, type: "asset", category: category("assets.cash") });
const receivables = account({ owner: anna, type: "asset", category: category("assets.receivables") });
const rentIncome = account({ owner: anna, type: "income", category: category("income.rent") });
const latePay = trigger("latePay");
const billedRent = cashflow({
cashAccount: cash,
schedule: schedule.monthly(),
amount: 12_000,
bookings: [
{ debit: cash, amount: (ctx) => ctx.amount / 2 },
{ debit: receivables, amount: (ctx) => ctx.amount / 2 },
{ credit: rentIncome, amount: (ctx) => ctx.amount },
],
triggers: latePay,
});
const delayedSettlement = cashflow({
cashAccount: cash,
schedule: schedule.onceAfterNoOfDays(30),
triggeredBy: latePay,
bookings: [
{ debit: cash, amount: (ctx) => ctx.source.amount / 2 },
{ credit: receivables, amount: (ctx) => ctx.source.amount / 2 },
],
});
const model = defineModel({
name: "late-rent-settlement",
currency: currencies.SEK,
timeline: periods.monthly({ from: "2026-01", count: 12 }),
entities: { anna },
accounts: { cash, receivables, rentIncome },
flows: { billedRent, delayedSettlement },
});
return model;The trigger carries an immutable snapshot. Later changes to the source flow do not change a payment already scheduled from that occurrence. Posting rows inherit their categories from the target accounts.