Cost center from the vendor
Invoices of known vendors get their cost center and G/L account from a table in the script. For an unknown vendor, the script attaches a hint to the approval so the invoice is allocated by hand. The workflow declares the cost center and G/L account fields itself. Who approves follows the invoice’s allocation in Finance, not the cost center field. With a card and a data table it needs no script: Allocation from a data table sets the invoice’s allocation in Finance.
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: cost-center-from-vendorname: Kostenstelle vom Lieferantentemplate: customtrigger: documentType: incoming-invoicefields: - key: costCenter kind: text labelDe: Kostenstelle labelEn: Cost center documentTypes: - incoming-invoice - key: glAccount kind: text labelDe: Sachkonto labelEn: G/L account documentTypes: - incoming-invoicestart: allocatesteps: - kind: script name: allocate label: Kostenstelle vom Lieferanten script: allocate.ts hook: onDocumentArrived inputs: - kind: field key: vendorName type: text returns: [] exits: [] 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: end name: approved label: Freigegeben outcome: approved - kind: end name: rejected label: Zurückgewiesen outcome: rejectedThe script allocate.ts
Section titled “The script allocate.ts”Hook: onDocumentArrived · Inputs: vendorName · Return values: none
import { defineScript } from '@acriva/workflow-sdk';
/** Cost center and G/L account (SKR 03) per vendor; a vendor matches when its name starts with the entry's name. */const ALLOCATION: readonly { vendor: string; costCenter: string; glAccount: string }[] = [ { vendor: 'Telekom', costCenter: '4400', glAccount: '4920' }, { vendor: 'Bürobedarf Schmidt', costCenter: '4200', glAccount: '4930' }, { vendor: 'Deutsche Bahn', costCenter: '4300', glAccount: '4663' },];
export default defineScript({ hook: 'onDocumentArrived', run(ctx) { const vendor = ctx.document.fields.vendorName; if (vendor == null) return; const match = ALLOCATION.find((entry) => vendor.toLowerCase().startsWith(entry.vendor.toLowerCase()), ); if (!match) { ctx.hint( `Für „${vendor}“ ist keine Kostenstelle hinterlegt. Bitte kontieren Sie die Rechnung von Hand.`, ); return; } ctx.setField('costCenter', match.costCenter); ctx.setField('glAccount', match.glAccount); },});What it does
Section titled “What it does”A test runs each of these cases in the sandbox and compares the result.
A known vendor
Section titled “A known vendor”- Input:
vendorNameTelekom Deutschland GmbH - Exit: the default next step
- Changes: field
costCenter=4400; fieldglAccount=4920
An unknown vendor
Section titled “An unknown vendor”- Input:
vendorNameNeue Firma AG - Exit: the default next step
- Changes: hint on the next task: “Für „Neue Firma AG“ ist keine Kostenstelle hinterlegt. Bitte kontieren Sie die Rechnung von Hand.”