Check the project budget
Invoices of a project are in its file of the file type project. You keep each project’s budget and the amount spent so far in a data table projekte with the project number as its key column, as the files are numbered; your controlling can update the amount spent regularly by an upload or through the API. The script looks up the invoice’s project in the table: when the invoice fits into the remaining budget, it goes to the normal approval with the budget left as a hint; when it exceeds it, the management approves. An invoice without a project file goes to the normal approval without a check.
The workflow
Section titled “The workflow”The workflow starts for every document of the type incoming-invoice. Its file workflow.yaml:
$schema: 'https://docs.acriva.de/schemas/workflow.schema.json'format: 1schemaVersion: 4sdk: '1.0.0'key: project-budgetname: Projektbudget prüfentemplate: customtrigger: documentType: incoming-invoicefields: []start: budgetsteps: - kind: script name: budget label: Projektbudget prüfen script: budget.ts hook: onDocumentArrived inputs: - kind: field key: totalGross type: money - kind: table key: projekte returns: - key: budget type: enumeration values: - within - exceeded branch: budget exits: - value: within next: approve - value: exceeded next: managementApproval next: approve - kind: humanTask name: approve label: Freigabe taskKind: approve assignees: - when: null assignee: kind: costCenterResponsible fallback: kind: role role: Buchhaltung options: excludeRequester: true excludeActorsOfSteps: [] pickFile: false next: approved onRejected: rejected - kind: humanTask name: managementApproval label: Freigabe Geschäftsführung taskKind: approve assignees: - when: null assignee: kind: role role: Geschäftsführung fallback: kind: role role: Buchhaltung options: excludeRequester: true excludeActorsOfSteps: [] pickFile: false next: approved onRejected: rejected - kind: end name: approved label: Freigegeben outcome: approved - kind: end name: rejected label: Zurückgewiesen outcome: rejectedThe script budget.ts
Section titled “The script budget.ts”Hook: onDocumentArrived · Inputs: totalGross, data table projekte · Return values: budget (within, exceeded)
import { defineScript, money } from '@acriva/workflow-sdk';
export default defineScript({ hook: 'onDocumentArrived', outputs: { budget: ['within', 'exceeded'] }, async run(ctx) { // An invoice outside a project's Akte goes on to its default next step, the normal approval. const project = ctx.document.files.find((file) => file.type === 'project'); if (!project) return; const row = await ctx.tables.lookup('projekte', project.number); if (row === null || row.budget === null) { ctx.hint( `Das Projekt ${project.number} steht nicht in der Projektliste; sein Budget ist nicht geprüft.`, ); return; } const name = row.bezeichnung ?? project.number; const left = money.round(row.budget - (row.verbraucht ?? 0)); const total = ctx.document.fields.totalGross ?? 0; if (total > left) { ctx.hint( `Die Rechnung über ${money.format(total)} übersteigt das Restbudget des Projekts ${name} von ${money.format(left)}.`, ); return ctx.branch('exceeded'); } ctx.hint( `Projekt ${name}: Nach dieser Rechnung bleiben ${money.format(money.round(left - total))} vom Budget.`, ); return ctx.branch('within'); },});What it does
Section titled “What it does”A test runs each of these cases in the sandbox and compares the result.
An invoice without a project
Section titled “An invoice without a project”- Input:
totalGross119 - Exit: the default next step
- Changes: none
An invoice above the remaining budget
Section titled “An invoice above the remaining budget”- Input:
totalGross11900 - Data table
projekte: 2 rowsprojektnummerP-2026-014,bezeichnungUmbau Lager Nord,budget50000,verbraucht41250.5projektnummerP-2026-021,bezeichnungMesse Hannover,budget18000,verbraucht2400
- Exit:
exceeded - Changes: hint on the next task: “Die Rechnung über 11.900,00 € übersteigt das Restbudget des Projekts Umbau Lager Nord von 8.749,50 €.”
A project missing from the list
Section titled “A project missing from the list”- Input:
totalGross595 - Data table
projekte: 2 rowsprojektnummerP-2026-014,bezeichnungUmbau Lager Nord,budget50000,verbraucht41250.5projektnummerP-2026-021,bezeichnungMesse Hannover,budget18000,verbraucht2400
- Exit: the default next step
- Changes: hint on the next task: “Das Projekt P-2026-099 steht nicht in der Projektliste; sein Budget ist nicht geprüft.”
An invoice within the budget
Section titled “An invoice within the budget”- Input:
totalGross2380 - Data table
projekte: 2 rowsprojektnummerP-2026-014,bezeichnungUmbau Lager Nord,budget50000,verbraucht41250.5projektnummerP-2026-021,bezeichnungMesse Hannover,budget18000,verbraucht2400
- Exit:
within - Changes: hint on the next task: “Projekt Umbau Lager Nord: Nach dieser Rechnung bleiben 6.369,50 € vom Budget.”