Batch-Uebermittlung (Phase 1): Collection + POST /v1/batch

Alternativer Uebermittlungsweg neben /v1/orders (unveraendert). Neue
Collection batch_submissions (Empfaengerschema Firma/Vorname/Nachname/
Zeile1-3/PLZ/Stadt/Land + Text ODER Druck-PDF, je Kunde ueber api_client).
Neuer Endpunkt POST /v1/batch: ein Empfaenger je Aufruf, PDF via
pdf_file_id (aus /v1/files) oder pdf_base64, oder text; Zeichen-Warnung
wie /v1/orders. Service-Policy darf batch_submissions lesen/als gebuendelt
markieren. Buendelung (xlsx+PDF+FTP) folgt in Phase 2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
s4luorth
2026-09-28 08:53:31 +02:00
parent 2438ecb491
commit 131c48485c
2 changed files with 95 additions and 0 deletions

View File

@@ -691,6 +691,30 @@ const collections = [
f('notified', 'boolean', { interface: 'boolean', default: false, note: 'Erinnerungs-Mail bereits verschickt (verhindert Wiederholung).' }),
{ field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} },
] },
// Alternativer Übermittlungsweg (Lettershop/FTP): je Empfänger ein Datensatz
// im festen Schema + fertige Druck-PDF ODER Schriftstücktext. Wird je Kunde
// täglich (03:00 Folgetag; Sa+So gemeinsam) zu einer xlsx + Sammel-Druck-PDF
// gebündelt und per FTP hochgeladen.
{ collection: 'batch_submissions', meta: { icon: 'inventory', note: 'Alternativer Übermittlungsweg: Empfängerzeile + Druck-PDF/Text; täglich je Kunde zu xlsx+PDF gebündelt (FTP).' }, fields: [
m2o('api_client', 'api_clients', { onDelete: 'CASCADE', note: 'Zugang, über den übermittelt wurde.' }),
m2o('customer', 'directus_users', { note: 'Kunde (Login-Konto) des Zugangs.' }),
f('firma', 'string', { interface: 'input' }),
f('vorname', 'string', { interface: 'input' }),
f('nachname', 'string', { interface: 'input' }),
f('zeile1', 'string', { interface: 'input' }),
f('zeile2', 'string', { interface: 'input' }),
f('zeile3', 'string', { interface: 'input' }),
f('plz', 'string', { interface: 'input' }),
f('stadt', 'string', { interface: 'input' }),
f('land', 'string', { interface: 'input' }),
f('text', 'text', { interface: 'input-multiline', note: 'Schriftstücktext (Handschrift), falls keine Druck-PDF.' }),
m2o('pdf_file', 'directus_files', { note: 'Fertige Druck-PDF (wird 1:1 übernommen), falls kein Text.' }),
dropdown('status', ['pending', 'bundled'], { default: 'pending', note: 'pending = noch nicht gebündelt.' }),
f('bundle_name', 'string', { interface: 'input', readonly: true, note: 'Name der Bündel-Datei, in die dieser Datensatz ging.' }),
f('bundled_at', 'timestamp', { interface: 'datetime', readonly: true }),
{ field: 'date_created', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} },
] },
];
// ── Schema anlegen ──────────────────────────────────────────────────────────
@@ -1161,6 +1185,10 @@ async function applyPermissions() {
// Hochgeladene Druckdateien lesen (Backend führt PDFs für den Charge-Sammeldruck
// zusammen und lädt sie dafür über /assets).
await ensurePermission(svcPol.id, 'directus_files', 'read');
// Alternativer Übermittlungsweg: Backend liest die Datensätze zum Bündeln und
// markiert sie danach als gebündelt.
await ensurePermission(svcPol.id, 'batch_submissions', 'read');
await ensurePermission(svcPol.id, 'batch_submissions', 'update', ['status', 'bundle_name', 'bundled_at']);
console.log(' Hinweis: Für Service einen Nutzer in Rolle "Service" anlegen und dessen',
'statischen Token in .env von Backend/Produktion eintragen.');