Public-API, mehrseitige Schriftstücke, manuelle Aufträge & Mailer
Public-API (neu, directus-extension-skrift-api): - Versionierter /v1-Namespace: POST /v1/orders, GET /v1/orders/:nr (Status pending/processing/shipped/cancelled), POST /v1/files (nur PDF, ≤80 MB). - Auth über X-Api-Key (Authorization ist von Directus reserviert), SHA-256-Hash. - Produkt-gebunden; Kuvert-only-Produkttyp; Kuvertformat automatisch (A4→DIN Lang, sonst C6); kein Platzhalter, kein Kunden-multipage/font_scale; Versandart englisch (single/bulk). - Selbst gehostete Swagger-UI-Doku (/docs) + OpenAPI (/v1/openapi.json), englisch/technisch. - Key-Hook (directus-extension-skrift-apikey): erzeugt Key automatisch, zeigt ihn einmalig in key_plain. Mehrseitige Schriftstücke: - generateLetterPages (Auto-Fluss, [[seitenumbruch]], Leerseiten-Filter). - Preview/Order-Generierung schreiben letter_NNN_pM.svg; Seiten-Übersicht im Neuauftrag. - Agent (skrift-agent): Seiten je Brief absteigend an den Plotter (Stapel-Reihenfolge). - countLetterPages + /api/order/pagecount für die Seiten-Vorschau. Manuelle Aufträge: - Schriftgröße (Brief/Kuvert), Signatur auf dem Brief mit X/Y/Größe-Feinjustierung, realistische Handschrift bis in den finalen Druck durchgereicht. - Spalten-Einfügen in der Empfängertabelle (Excel-Spalte je Zelle). Mailer: Text-Alternative + Reply-To (Zustellbarkeit). App: Freitext in Musteranfrage, Konfigurator-Reset, Lightbox-Seitenverhältnis + Bild-Download, Sticky-Vorschau-Fix, Tab-Eingabe + Rechtsbündigkeit, Leerzeilen-Trim. Bootstrap: neue Felder (font_scale_*, signatures_manual, multi_page, page_count, realistic, shipping_day, api_client) + Collections api_clients, Produkttyp envelope. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -157,7 +157,7 @@ const collections = [
|
||||
f('key', 'string', { interface: 'input', unique: true, required: true }),
|
||||
f('name', 'string', { interface: 'input', required: true }),
|
||||
f('description', 'text', { interface: 'input-multiline' }),
|
||||
dropdown('type', ['letter', 'postcard', 'sample', 'contact'], { required: true }),
|
||||
dropdown('type', ['letter', 'postcard', 'envelope', 'sample', 'contact'], { required: true }),
|
||||
dropdown('visibility', ['alle', 'privat', 'unternehmen'], { default: 'alle', note: 'Für wen im Konfigurator sichtbar.' }),
|
||||
dropdown('pricing_mode', ['formel', 'auf_anfrage'], { default: 'formel' }),
|
||||
f('base_price', 'float', { interface: 'input', note: 'Basispreis (netto). Leer bei auf_anfrage.' }),
|
||||
@@ -249,7 +249,15 @@ const collections = [
|
||||
m2o('format', 'formats'),
|
||||
dropdown('person_type', ['privat', 'unternehmen'], { default: 'privat' }),
|
||||
dropdown('font', ['tilda', 'alva', 'ellie']),
|
||||
dropdown('source', ['configurator', 'portal', 'operator', 'extern'], { default: 'configurator', note: '„extern" = Bestellung über eine andere Plattform (z. B. Etsy), ohne Preis/Zahlung.' }),
|
||||
f('realistic', 'boolean', { interface: 'boolean', default: true, note: 'Natürliche Handschrift-Variation (Jitter/Neigung).' }),
|
||||
m2o('api_client', 'api_clients', { onDelete: 'SET NULL', note: 'Gesetzt bei Aufträgen über die Public-API.' }),
|
||||
dropdown('shipping_day', ['montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag', 'sonntag'], { note: 'Vom Kunden gewünschter Versandtag (optional, v. a. Public-API).' }),
|
||||
f('font_scale_letter', 'float', { interface: 'input', default: 1, note: 'Relative Schriftgröße Brief (0.8–1.5, 1 = Standard).' }),
|
||||
f('font_scale_envelope', 'float', { interface: 'input', default: 1, note: 'Relative Schriftgröße Kuvert (0.8–1.5, 1 = Standard).' }),
|
||||
f('signatures_manual', 'json', { interface: 'input-code', note: 'Signatur(en) auf dem Brief bei manuellen Aufträgen: { signatures:{signatur1:svg}, offsets:{signatur1:{x,y,scale}} }.' }),
|
||||
f('multi_page', 'boolean', { interface: 'boolean', default: false, note: 'Mehrseitiges Schriftstück (Auto-Fluss über mehrere A4-Seiten).' }),
|
||||
f('page_count', 'integer', { interface: 'input', note: 'Seiten je Schriftstück (bei mehrseitig; wird bei der Generierung gesetzt).' }),
|
||||
dropdown('source', ['configurator', 'portal', 'operator', 'extern', 'api'], { default: 'configurator', note: '„extern" = andere Plattform (z. B. Etsy); „api" = Public-API-Zugang.' }),
|
||||
dropdown('status', ['entwurf', 'vorbereitet', 'wartet_auf_zahlung', 'bezahlt', 'material_erwartet',
|
||||
'material_eingegangen', 'in_queue', 'in_produktion', 'gedruckt', 'versendet', 'abgeschlossen', 'storniert'],
|
||||
{ default: 'entwurf' }),
|
||||
@@ -438,6 +446,24 @@ const collections = [
|
||||
{ field: 'timestamp', type: 'timestamp', meta: { interface: 'datetime', readonly: true, special: ['date-created'] }, schema: {} },
|
||||
] },
|
||||
|
||||
// API-Zugänge für Kunden (Public-API). Keys werden nur als SHA-256-Hash gespeichert.
|
||||
{ collection: 'api_clients', meta: { icon: 'vpn_key', note: 'API-Zugänge für Kunden (Public-API).' }, fields: [
|
||||
f('name', 'string', { interface: 'input', required: true, note: 'Bezeichnung, z. B. Firmenname.' }),
|
||||
f('key_plain', 'string', { interface: 'input', note: 'Wird beim Anlegen automatisch erzeugt und EINMALIG angezeigt – jetzt kopieren! Verschwindet bei der nächsten Änderung. Nur der Hash bleibt gespeichert.' }),
|
||||
f('key_prefix', 'string', { interface: 'input', note: 'Erkennungspräfix des Keys (nur Anzeige).' }),
|
||||
f('key_hash', 'string', { interface: 'input', note: 'SHA-256 des API-Keys – automatisch gesetzt. Nicht manuell ändern.' }),
|
||||
m2o('customer', 'directus_users', { note: 'Verknüpftes Kundenkonto (optional).' }),
|
||||
m2o('product', 'products', { nullable: false, note: 'Einziges Produkt, das dieser Zugang bestellen darf.' }),
|
||||
f('active', 'boolean', { interface: 'boolean', default: true }),
|
||||
f('webhook_url', 'string', { interface: 'input', note: 'Optionaler Webhook für Statusänderungen (derzeit ungenutzt – Kunde pollt).' }),
|
||||
f('config', 'json', { interface: 'input-code', note: 'Kundenspezifische Konfiguration (optional).' }),
|
||||
f('last_used', 'timestamp', { interface: 'datetime' }),
|
||||
// AGB/Vertrag – einmalige Zustimmung beim Onboarding festhalten (Nachweis).
|
||||
f('terms_version', 'string', { interface: 'input', note: 'Akzeptierte AGB-Version, z. B. „2026-01".' }),
|
||||
f('terms_accepted_at', 'timestamp', { interface: 'datetime', note: 'Zeitpunkt der AGB-/Vertragszustimmung.' }),
|
||||
f('contract_ref', 'string', { interface: 'input', note: 'Referenz zum unterschriebenen Vertrag (Aktenzeichen/Link).' }),
|
||||
] },
|
||||
|
||||
// Unterschriften je Kunde (SVG-Datei). Wird am Kundenkonto als o2m gezeigt.
|
||||
{ collection: 'signatures', meta: { icon: 'draw', note: 'Unterschriften je Kunde.' }, fields: [
|
||||
m2o('customer', 'directus_users', { onDelete: 'CASCADE' }),
|
||||
|
||||
Reference in New Issue
Block a user