Skip to content

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 starts for every document of the type incoming-invoice. Its file workflow.yaml:

$schema: 'https://docs.acriva.de/schemas/workflow.schema.json'
format: 1
schemaVersion: 4
sdk: '1.0.0'
key: cost-center-from-vendor
name: Kostenstelle vom Lieferanten
template: custom
trigger:
documentType: incoming-invoice
fields:
- key: costCenter
kind: text
labelDe: Kostenstelle
labelEn: Cost center
documentTypes:
- incoming-invoice
- key: glAccount
kind: text
labelDe: Sachkonto
labelEn: G/L account
documentTypes:
- incoming-invoice
start: allocate
steps:
- 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: rejected

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);
},
});

A test runs each of these cases in the sandbox and compares the result.

  • Input: vendorName Telekom Deutschland GmbH
  • Exit: the default next step
  • Changes: field costCenter = 4400; field glAccount = 4920
  • Input: vendorName Neue 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.”