beaa1be4a5
Build and Push Multi-Platform Images / build-and-push (push) Successful in 31s
E-Mail-Import und External-Upload setzen ASN, Custom Fields (CF3/CF7/CF9), Dokumenttyp, Tags, Owner und Belegdatum jetzt bereits beim post_document, statt erst nachträglich über den Task-Processor-Cron (30 s + PATCH). - Neu: deriveTaskMetadata() in task-metadata.util.ts als gemeinsame Ableitung (Task-Felder → Paperless-Metadaten) für beide Upload-Pfade und den Task-Processor – identische Parsing-Regeln, kein Copy-Paste - Task-Processor nutzt den Helper (verhaltensidentischer Refactor) und patcht weiterhin idempotent nach; zuständig bleibt er für alles ID-Abhängige (CF8-Verknüpfungen, Anlage-Titel, Owner-Entfernung, Notizen) - FAILURE-Zweig loggt Paperless-Fehlertext und Belegnummer vor dem Löschen des Tasks (ASN-Kollision kann jetzt den Consume scheitern lassen) - Tests: 18 Unit-Tests für deriveTaskMetadata, 3 Charakterisierungstests pinnen den PATCH-Payload von processSuccessfulTask Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
140 lines
4.9 KiB
TypeScript
140 lines
4.9 KiB
TypeScript
import { deriveTaskMetadata } from './task-metadata.util';
|
|
|
|
describe('deriveTaskMetadata', () => {
|
|
describe('archiveSerialNumber', () => {
|
|
it('parst ASN aus Asn und entfernt alle Nicht-Ziffern', () => {
|
|
const result = deriveTaskMetadata({ Asn: 'ASN-123' });
|
|
expect(result.archiveSerialNumber).toBe(123);
|
|
});
|
|
|
|
it('leitet ASN aus InterneBelegnummer ab (nur Bindestriche entfernen)', () => {
|
|
const result = deriveTaskMetadata({ InterneBelegnummer: '2026-000123' });
|
|
expect(result.archiveSerialNumber).toBe(2026000123);
|
|
});
|
|
|
|
it('bevorzugt Asn vor InterneBelegnummer', () => {
|
|
const result = deriveTaskMetadata({
|
|
Asn: '42',
|
|
InterneBelegnummer: '2026-000123',
|
|
});
|
|
expect(result.archiveSerialNumber).toBe(42);
|
|
});
|
|
|
|
it('nutzt keinen Belegnummer-Fallback, wenn Asn gesetzt aber unparsebar ist', () => {
|
|
// Entspricht exakt der Processor-Logik: Fallback nur bei leerem Asn
|
|
const result = deriveTaskMetadata({
|
|
Asn: 'abc',
|
|
InterneBelegnummer: '2026-000123',
|
|
});
|
|
expect(result.archiveSerialNumber).toBeUndefined();
|
|
});
|
|
|
|
it('lässt ASN weg, wenn InterneBelegnummer nicht parsebar ist', () => {
|
|
const result = deriveTaskMetadata({ InterneBelegnummer: 'Beleg-X' });
|
|
expect(result.archiveSerialNumber).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('customFields (CF7/CF3/CF9)', () => {
|
|
it('setzt CF7 aus InterneBelegnummer', () => {
|
|
const result = deriveTaskMetadata({ InterneBelegnummer: '2026-000123' });
|
|
expect(result.customFields['7']).toBe('2026-000123');
|
|
});
|
|
|
|
it('setzt CF3 aus externeBelegnummer', () => {
|
|
const result = deriveTaskMetadata({ externeBelegnummer: 'RE-4711' });
|
|
expect(result.customFields['3']).toBe('RE-4711');
|
|
});
|
|
|
|
it('setzt CF9 aus Eingangsdatum als YYYY-MM-DD', () => {
|
|
const result = deriveTaskMetadata({
|
|
Eingangsdatum: new Date('2026-07-14T10:30:00Z'),
|
|
});
|
|
expect(result.customFields['9']).toBe('2026-07-14');
|
|
});
|
|
|
|
it('übernimmt CustomFieldsJson als Basis mit normalisierten numerischen Keys', () => {
|
|
const result = deriveTaskMetadata({
|
|
CustomFieldsJson: JSON.stringify({ '4': 'wert4', abc: 'ignoriert' }),
|
|
});
|
|
expect(result.customFields).toEqual({ '4': 'wert4' });
|
|
});
|
|
|
|
it('überschreibt CustomFieldsJson-Basis mit dedizierten Feldern CF7/CF3/CF9', () => {
|
|
const result = deriveTaskMetadata({
|
|
InterneBelegnummer: '2026-000123',
|
|
externeBelegnummer: 'RE-4711',
|
|
Eingangsdatum: new Date('2026-07-14T00:00:00Z'),
|
|
CustomFieldsJson: JSON.stringify({
|
|
'7': 'alt7',
|
|
'3': 'alt3',
|
|
'9': 'alt9',
|
|
}),
|
|
});
|
|
expect(result.customFields['7']).toBe('2026-000123');
|
|
expect(result.customFields['3']).toBe('RE-4711');
|
|
expect(result.customFields['9']).toBe('2026-07-14');
|
|
});
|
|
|
|
it('ignoriert ungültiges CustomFieldsJson still', () => {
|
|
const result = deriveTaskMetadata({
|
|
CustomFieldsJson: '{kein json',
|
|
InterneBelegnummer: '2026-000123',
|
|
});
|
|
expect(result.customFields).toEqual({ '7': '2026-000123' });
|
|
});
|
|
|
|
it('liefert leeres customFields-Objekt ohne Eingaben', () => {
|
|
const result = deriveTaskMetadata({});
|
|
expect(result.customFields).toEqual({});
|
|
});
|
|
});
|
|
|
|
describe('documentType / created / owner / tags', () => {
|
|
it('übernimmt DocumentType nur wenn truthy', () => {
|
|
expect(deriveTaskMetadata({ DocumentType: 5 }).documentType).toBe(5);
|
|
expect(
|
|
deriveTaskMetadata({ DocumentType: 0 }).documentType,
|
|
).toBeUndefined();
|
|
expect(
|
|
deriveTaskMetadata({ DocumentType: null }).documentType,
|
|
).toBeUndefined();
|
|
});
|
|
|
|
it('leitet created als ISO-String aus Belegdatum ab', () => {
|
|
const result = deriveTaskMetadata({
|
|
Belegdatum: new Date('2026-07-01T00:00:00Z'),
|
|
});
|
|
expect(result.created).toBe('2026-07-01T00:00:00.000Z');
|
|
});
|
|
|
|
it('setzt owner nur bei truthy BetriebID', () => {
|
|
expect(deriveTaskMetadata({ BetriebID: 3 }).owner).toBe(3);
|
|
expect(deriveTaskMetadata({ BetriebID: null }).owner).toBeUndefined();
|
|
expect(deriveTaskMetadata({}).owner).toBeUndefined();
|
|
});
|
|
|
|
it('parst Tags-CSV und filtert Ungültiges', () => {
|
|
const result = deriveTaskMetadata({ Tags: '1, 2, x' });
|
|
expect(result.tags).toEqual([1, 2]);
|
|
});
|
|
|
|
it('lässt tags bei leerem Tags-Feld weg', () => {
|
|
expect(deriveTaskMetadata({ Tags: null }).tags).toBeUndefined();
|
|
expect(deriveTaskMetadata({}).tags).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('leere Eingaben', () => {
|
|
it('lässt bei leeren Strings alle Felder weg', () => {
|
|
const result = deriveTaskMetadata({
|
|
InterneBelegnummer: '',
|
|
Asn: '',
|
|
externeBelegnummer: '',
|
|
Tags: '',
|
|
});
|
|
expect(result).toEqual({ customFields: {} });
|
|
});
|
|
});
|
|
});
|