Zum Inhalt springen

Buchungsfelder vorbereiten

Der Workflow legt die Felder Buchungstext und Sachkonto an und füllt sie, sobald eine Rechnung eingeht: den Buchungstext aus Lieferant und Rechnungsnummer mit höchstens 60 Zeichen, wie DATEV ihn annimmt, und das Sachkonto aus einer Tabelle im Skript. Ein zu langer Lieferantenname wird an einer Wortgrenze gekürzt, damit die Rechnungsnummer vollständig bleibt. Die Felder stehen am Dokument für die Buchhaltung bereit; der DATEV-Export bildet seinen Buchungstext selbst aus Lieferant und Rechnungsnummer und liest diese Felder nicht.

Der Workflow startet für jedes Dokument vom Typ incoming-invoice. Seine Datei workflow.yaml:

$schema: 'https://docs.acriva.de/schemas/workflow.schema.json'
format: 1
schemaVersion: 4
sdk: '1.0.0'
key: datev-fields
name: Buchungsfelder vorbereiten
template: custom
trigger:
documentType: incoming-invoice
fields:
- key: bookingText
kind: text
labelDe: Buchungstext
labelEn: Booking text
documentTypes:
- incoming-invoice
- key: glAccount
kind: text
labelDe: Sachkonto
labelEn: G/L account
documentTypes:
- incoming-invoice
start: prepare
steps:
- kind: script
name: prepare
label: DATEV-Felder vorbereiten
script: prepare.ts
hook: onDocumentArrived
inputs:
- kind: field
key: vendorName
type: text
- kind: field
key: invoiceNumber
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 · Eingaben: vendorName, invoiceNumber · Rückgaben: keine

import { defineScript } from '@acriva/workflow-sdk';
/** DATEV takes at most 60 characters as the booking text. */
const MAX_BOOKING_TEXT = 60;
/** The G/L account (SKR03) per vendor; a vendor matches when its name starts with the entry's name. */
const GL_ACCOUNTS: readonly { vendor: string; glAccount: string }[] = [
{ vendor: 'Telekom', glAccount: '4920' },
{ vendor: 'Deutsche Bahn', glAccount: '4663' },
{ vendor: 'Bürobedarf', glAccount: '4930' },
];
/**
* The vendor and the invoice number in at most 60 characters. A vendor that is too long is cut at a word boundary, so the
* invoice number always stays complete.
*/
function bookingText(vendor: string, invoiceNumber: string | null): string {
const suffix = invoiceNumber == null ? '' : ` ${invoiceNumber}`;
const full = `${vendor}${suffix}`;
if (full.length <= MAX_BOOKING_TEXT) return full;
const room = MAX_BOOKING_TEXT - suffix.length;
if (room <= 0) return suffix.trim().slice(0, MAX_BOOKING_TEXT);
// Keep one character more, so a word that ends exactly at the limit stays whole.
const head = vendor.slice(0, room + 1);
const space = head.lastIndexOf(' ');
const shortVendor = (space > 0 ? head.slice(0, space) : vendor.slice(0, room)).trimEnd();
return `${shortVendor}${suffix}`;
}
export default defineScript({
hook: 'onDocumentArrived',
run(ctx) {
const { vendorName, invoiceNumber } = ctx.document.fields;
if (vendorName == null) return;
ctx.setField('bookingText', bookingText(vendorName.trim(), invoiceNumber?.trim() || null));
const match = GL_ACCOUNTS.find((entry) =>
vendorName.toLowerCase().startsWith(entry.vendor.toLowerCase()),
);
if (match) {
ctx.setField('glAccount', match.glAccount);
} else {
ctx.hint(
'Für diesen Lieferanten ist kein Sachkonto hinterlegt. Bitte ergänzen Sie es von Hand.',
);
}
},
});

Ein Test führt jeden dieser Fälle in der Sandbox aus und vergleicht das Ergebnis.

  • Eingabe: vendorName Telekom Deutschland GmbH, invoiceNumber 4711-2026-10
  • Ausgang: der Standard-Nachfolger
  • Änderungen: Feld bookingText = Telekom Deutschland GmbH 4711-2026-10; Feld glAccount = 4920
  • Eingabe: vendorName Gebäudereinigung Sauber & Glanz Facility Services Deutschland GmbH, invoiceNumber RE-2026-0815
  • Ausgang: der Standard-Nachfolger
  • Änderungen: Feld bookingText = Gebäudereinigung Sauber & Glanz Facility RE-2026-0815; Hinweis an der nächsten Aufgabe: „Für diesen Lieferanten ist kein Sachkonto hinterlegt. Bitte ergänzen Sie es von Hand.“
  • Eingabe: vendorName null, invoiceNumber RE-2026-0815
  • Ausgang: der Standard-Nachfolger
  • Änderungen: keine