Commit Graph

10 Commits

Author SHA1 Message Date
Lucas Orth
57d48409e6 Kontakt-CRM, Chargen-Sammeldruck, API-Status & Auto-Generierung
Kontakte/CRM (Directus):
- Neue Collections `contacts` (Leads) + `contact_actions` (Rückruf/Angebot/Mail).
- Hook `skrift-contacts`: Kontakte werden nur auf Anforderung angelegt
  (Auftrag "In Kontakte speichern"); Rückruf-Erinnerung (Zeitplan) und
  Angebots-/Mail-an-mich-Mails; Auto-Löschung nur bei Lead-Status
  "kein_interesse" nach 30 Tagen; optionaler DSGVO-Strip (per Env, Dry-Run).
- Modul `skrift-kontakte`: handytaugliches Board (Anruf via groundwire:,
  Notizen mit Autosave, Durchblättern, CSV-Export, Aktionen als Buttons).

API-Chargen & PDF-Sammeldruck:
- Produktions-Board gruppiert API-Aufträge unter "Neu" zu Chargen
  (Kunde + Typ + Versandtag + Eingangstag), aufklappbar, mit "fällig bis"
  (Versandtag der übernächsten Woche).
- Mehrfachauswahl -> Sammel-PDF (Backend `pdf-lib`, /api/charge/merge-pdf,
  Directus-Proxy /skrift-orders/charge/pdf), Kuverts an Plotter und
  Sammel-Status; PDF- und Kuvert-Reihenfolge nach Auftragsnummer (Kollation).
- Mailer: keine Einzelmail je API-Auftrag mehr, stattdessen Tagesübersicht
  (18:00) pro Kunde, nach Versandtag aufgeschlüsselt.

Status-API & Generierung:
- Public-API-Status liest jetzt production_status (Board) statt nur
  kaufmännischem Status; neues Feld `status_since` in der Antwort.
- Auftrag stempelt `production_status_changed_at` bei jedem Statuswechsel.
- Generierung wird IMMER beim Eingang angestoßen (auch Datei-Produkte mit
  handgeschriebenem Kuvert), nicht nur bei letter/postcard.
- Versandtag im Produktionsdashboard sichtbar.

Rechte: Service-Rolle darf directus_files lesen (Backend lädt PDFs für den
Sammeldruck über /assets).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-21 08:53:08 +02:00
Lucas Orth
c535af5781 API: mehrere Produkte je Zugang (m2m) + Produktwahl im Order-Request
- api_clients bekommt ein m2m-Feld `products` (Mehrfachauswahl) über die neue
  Junction `api_client_products`; das Einzelfeld `product` bleibt als Fallback.
- POST /v1/orders: neues Pflichtfeld `product` (Produkt-Key) wählt aus den
  erlaubten Produkten; bei genau einem optional. Ungültig/fehlend → 400 mit
  Liste der erlaubten Keys.
- POST /v1/clients akzeptiert `products: [id, …]`.
- Doku (Swagger UI) + OpenAPI um das product-Feld ergänzt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 11:25:46 +02:00
Lucas Orth
1d5c1a14d4 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>
2026-08-18 10:01:53 +02:00
Lucas Orth
db419bf8eb Tabulator-Support in Brieftexten + ausstehende Batches
Tabs (Eingabe + Rendering):
- Tab-Taste fügt echten Tabulator ein (App-Konfigurator + Directus
  manueller Druck); \t in beiden Zeichen-Whitelists erlaubt.
- Renderer: Zeilen mit führenden Tabs werden nicht mehr nach Wortbreite
  umgebrochen; Tab-Spruenge an den rechten Rand geclampt; bei Ueberlauf
  rechtsbuendig (Datum ganz rechts, ohne Absturz nach links). Tab-loser
  Text bleibt bit-identisch.

Mailer:
- loadSettings bricht nicht mehr ab, wenn team_email fehlt (Team-
  Empfaenger separat gelesen).
- Eingebaute Fallback-Vorlagen fuer order_created + Status-Mails, damit
  Bestaetigung/Status auch ohne DB-Vorlage zugestellt werden.

Weitere ausstehende Arbeit:
- Abweichender Text je Schriftstueck (#5) in Generierung/Konfigurator.
- Produktions-Board: Format-Sammelgruppen (Bulk) + Bootstrap-Feld.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 16:32:11 +02:00
Lucas Orth
0b2f2ba50a Postkarten-Maße-Fix, Sammelversand-Staffel, Extern-Format, Mustertexte
- render_formats: Upsert statt nur-anlegen → korrekte A6-Maße werden beim
  Bootstrap erzwungen (behebt „Postkarten passen nicht, weder quer noch hoch")
- Sammelversand-Staffel: bis 5 Schriftstücke 1,80 € (neues Preisitem
  sammelversand_klein), ab 6 der reguläre Satz – Backend + App-Option
- Extern-Modus: Postkarten-Format (hoch/quer) wieder wählbar; optionaler
  ?format=-Parameter; kein Auto-Vorbelegen bei mehreren Formaten
- Unbegrenzte Mustertexte: neue Collection muster_texts (Dropdown im
  „Manueller Druck", Du/Sie als Fallback + Seeds)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 07:49:22 +02:00
Lucas Orth
3cb93d078e Unterschriftenservice, Extern-Modus, Adressmodell, Alt-Mail, Team-Mails
skrift-app (Konfigurator):
- Datei-Produkte (Unterschriftenservice): Mehrfach-Upload (PDF/Word/Excel),
  komplett preisfrei (keine Preisleiste/Aufpreise/Kostenübersicht/Zahlung)
- Extern-/Etsy-Modus (?extern=1&versand&kuvert&beschriftung&menge): vom Betreiber
  vorkonfiguriert, Kunde füllt nur Empfänger/Text/Rechnungsdaten/Übersicht,
  keine Preise/Zahlung; Menge greift immer (auch >25 / ohne Empfänger); eigener
  Danke-Text
- Adressmodell: zwei feste Adressen (Rechnung/Lieferung) ohne Namen statt
  Dropdown; Auto-Vorbefüllung; Lieferadresse nur bei Sammelversand; abweichende
  Lieferadresse per Default aus; Pflichtfelder erzwungen
- Platzhalter-Tabelle immer im Text-Schritt (auch Sammelversand ohne Kuvert) +
  Excel; Tabellen-Eingabe nur bis 25, „Ab 26"-Hinweis entfernt
- Stammdaten: zwei Adressblöcke + Erfolgsmeldung

Directus/Backend:
- Signatur-Endpunkte /signature-preview + /signature-render (Proxy zum
  signature-service, Marker + Konto-Offsets), Modul-Reiter „Unterschriften"
  (aus Auftrag oder manuell), Tabelle über volle Breite
- Generierung läuft bei jeder Bestellung; Kuverts immer (Datei-Produkt: nur
  Kuvert, DIN Lang als Default); source_files am Auftrag
- Produktions-Board: „Dateien"-Button (hochgeladene Originale, keine SVGs)
- Alt-Mail-Login: Zweit-Mails melden im selben Konto an (skrift-auth)
- Team-Mails schlank + konfigurierbar (email_settings.team_email) für
  Bestellung/Muster/Anfrage; keine Bestellbestätigung bei Datei-Produkten,
  separate Vorlagen unterschriften_eingang/extern_eingang
- Rechnungsadresse wird ins Konto übernommen, wenn dort noch keine steht
- Kunden-Policy: directus_files create/read (Upload); Bootstrap: users
  billing_address/shipping_address/alt_emails, orders.source_files/source=extern,
  signatures marker/offsets, unterschriftenservice input_mode=datei/pricing_mode=formel

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 14:52:09 +02:00
Lucas Orth
6232cecdb1 Produktion: Format-Warteschlangen, Sammeldruck, Webhook, Preis-a/e
Produktions-Board:
- Massenauswahl (+ "Alle auswählen") mit Sammel-Druck und Sammel-Status
- Warteschlange je Maschine nach Format gebündelt; Formatabfrage
  (machines.current_format) statt automatischem Anschluss
- resiliente Ladeabfragen (Board bleibt ohne neue Felder nutzbar)

Agent (skrift-agent):
- druckt strikt ein Dokument nach dem anderen (Idle-Gate) -> behebt
  Verlust von Folgejobs während eines laufenden Drucks
- druckt nur Jobs des eingelegten Formats (current_format), kein Auto-Anschluss
- Heartbeat gedrosselt (nur bei Statuswechsel / alle 60 s)

Neues Modul "Manueller Druck" (skrift-neuauftrag):
- interner Auftrag ohne Zahlung, Vorschau, Platzhalter/Excel-Import,
  Felder bleiben nach dem Absenden stehen

Backend/Endpunkte (skrift-orders):
- jobs tragen format/format_label; /enqueue-bulk für Sammeldruck
- Webhook /inbound/:kind (JetFormBuilder) mit Token + tolerantem Body-Parser
- Kleinmengen-Aufschlag je Produkt über Faktoren a (Deckel) und e (Exponent)
- Fix: norm()-Shadowing in calculatePrice (norm is not a function)

Bootstrap:
- jobs.format/format_label, machines.current_format
- products.price_factor_a/e; Multiplikator-Formel auf a/e umgestellt inkl.
  verhaltensneutraler Migration bestehender Formel/Produkte

skrift-app (Konfigurator):
- Zeilenumbrüche im Textfeld erlaubt; Umschlag-Individualtext als Textfeld
- Platzhalter-Tabelle im Text-Schritt immer verfügbar (auch Sammelversand
  ohne Kuvert) inkl. Excel-Upload nur für Platzhalterwerte
- Danke-Seite: Button zurück zu skrift.de
- z-index-Fix: Platzhalter-Tabelle überlagert die Vorschau nicht mehr

WordPress-Preisrechner: a/e-Faktoren in PHP- und JS-Rechnung
Directus: SKRIFT_WEBHOOK_TOKEN in compose/.env.example

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 11:51:24 +02:00
Lucas Orth
f77ddb6a4c Formate zentral aus Directus + Kuvert-/Agent-/Login-Fixes
Formate zentralisiert (Phase 1)
- Neue Collection render_formats (Seitengröße, Ränder, Zeilenhöhe/-limit +
  Plotter-Template) als einzige Quelle. Backend liest sie gecacht (Start +
  stündlich, synchroner Zugriff → keine Latenz) mit eingebauten Defaults als
  Fallback; manueller Trigger via POST /api/formats/refresh.
- Ermöglicht frei definierbare Formate ohne Codeänderung.

Kuvert-Templates
- Werte 1:1 aus dem alten Job-Manager übernommen (falsche/vertauschte Maße
  korrigiert, per Upsert) und je Format die zweite Variante ergänzt
  (individuelle Beschriftung). Druck-Popup schlägt bei freiem Text Variante 2 vor.

Produktions-Agent
- Datei-Endpunkt liefert {files} ohne data-Hülle → eigener get_raw statt des
  data-auspackenden get; Dokumentauswahl positionsbasiert (robust gegen 0-/1-
  basierte Dateinamen).

Bootstrap
- Ungültiger DIRECTUS_TOKEN wird erkannt und fällt auf ADMIN_EMAIL/PASSWORD
  zurück, statt mit einem 401 abzubrechen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 09:05:09 +02:00
Lucas Orth
06c4078290 Produktions-Modul, überarbeitete Preislogik und WordPress-Preisrechner
Directus
- Neues Modul „Produktion": Board mit Neu/Warteschlange/Im Druck/
  Kuvertierung/Versandfertig/Versendet/Archiv, zentraler Suche, Druck-Popup
  (Maschine, Template, Maße, Nummernbereich, Direktdruck vs. Warteschlange)
  und Empfängerliste mit Vorschau von Schriftstück und Kuvert.
- Interface-Plugins: Auftragsdateien, Drucken, Testdruck, Empfängersuche.
- Mailer-Hook für Auftrags- und Statusmails inkl. Signatur und AGB-Anhang.
- Auftrag: Empfängerzeilen inline, Produktionsstatus (inkl. storniert),
  Versanddatum, Brief-/Kuvert-Indikatoren, Insights-Dashboard.
- Absender aller Mails ist Skrift (Projektname + email_settings); die
  Angebotsanfrage nennt jetzt das angefragte Produkt.

Preislogik
- Eine gemeinsame Multiplikator-Formel; Normalpreis-Menge je Produkt
  (products.norm_qty). Alte B2B/B2C-Fallback-Felder entfernt.
- Mengenrabatt-Staffel (ab X Stück Y %) in den Preis-Einstellungen.
- Preis pro Stück ohne einmalige Kosten (unit_net_total).
- Einzelversand rechnet Kuvert und Beschriftung nicht mehr doppelt.
- Fehlerhafte Grundpreis-Formel legt die Preisauskunft nicht mehr lahm.
- Briefnummern 1-basiert: Dateiname entspricht der Briefnummer.

app.skrift.de
- Direktlinks für Muster, Unterschriftenservice und Follow-ups; Muster als
  eigene Seite, Kontaktprodukte direkt im Anfrageformular.
- Mehrere Adressen in den Stammdaten plus Adressauswahl im Konfigurator.
- Verbotene Zeichen werden bei der Eingabe entfernt und gemeldet.
- Zeilenüberlauf als Fehlerkasten vor „Weiter"; Mengenfeld leerbar,
  Standardmenge 100; Checkout-Checkboxen im Kartenstil.

Produktion
- skrift-agent: Poll-Modell je Maschine, Maß-Übersteuerung, Nummernfilter
  und automatischer Übergang in die Kuvertierung.

WordPress
- Neues Plugin „Skrift Preisrechner": Shortcodes inkl./exkl. MwSt,
  stündlicher Abgleich der Preisdaten in WordPress und ein sicherer
  Formel-Interpreter, damit Formeländerungen automatisch greifen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:24:12 +02:00
Lucas Orth
2dbbc4611a Directus als Daten-/Auth-Schicht + Backend-Anbindung
Directus (Postgres, hinter NPM) wird die zentrale Datenquelle für Kunden,
Aufträge, Produkte, Preise und Gutscheine; das skrift-backend bleibt reine
Generierungs-Engine.

- Docker/directus: docker-compose (Directus 11 + Postgres), Bootstrap-Skript
  legt Collections, Rollen/Policies/Rechte und Seed idempotent an.
- Extension skrift-auth: passwortloser Login per E-Mail-Code (Codes nur als
  Hash, Ablauf, Versuchslimit) sowie Kontoanlage aus dem Checkout.
- Extension skrift-orders: kontrollierter Bestell-Endpunkt für Gäste und
  eingeloggte Kunden; Preis wird immer serverseitig berechnet (editierbare
  Formel via sicherem Interpreter, Werte aus price_items).
- skrift-backend: neuer Endpunkt /api/order/from-directus erzeugt SVGs aus
  einem Directus-Auftrag und schreibt Status + artifact_path zurück. Dafür
  wurde die Kernlogik aus generateOrder als runGeneration herausgelöst
  (Verhalten unverändert); generateOrder ist jetzt ein HTTP-Wrapper.
- compose: NPM-Netz ergänzt, API_TOKEN/DIRECTUS_* werden durchgereicht.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 19:13:35 +02:00