Skip to content

1.7.5

⚙️ Patch 1.7.5 — Tickets AI workflow v2 (n8n payload, live updates, agents)

🚀 Summary

  • Tickets n8n integration upgraded: lean webhook payload with conversation context, order IDs, attachment proxy URLs, and optional PDF drafts from n8n callbacks.
  • Live UI updates via WebSocket (/api/v1/tickets/ws) — replaces polling GET /ai-responses while waiting for n8n.
  • Six specialist n8n agents documented (German system prompts): damaged, wrong/missing, delivery, order, refund/return, general — see docs/docs/services/service_tickets/n8n-agent-prompts.md.
  • Messages UI shows inbound customer messages only; shop replies appear on the AI draft side. Editable issue category per ticket.
  • Per-message response sync (ticket_message_responses) and closed-ticket training pairs for future AI training.
  • Plenty send supports PDF attachments from n8n drafts; reply payload matches Plenty backend UI shape.

✨ Improvements

Tickets — n8n webhook payload

  • build_generate_webhook_payload sends a deduplicated structure:
  • ticket — title, plain-text body, external_order_id, order_id, customer emails, target attachments.
  • conversation[] — inbound customer messages only (oldest first), each with optional ai_response for prior replies.
  • Shop/outbound messages (newReplyFromUser, from.type=user, linkedTo) are not duplicated as conversation entries.
  • external_order_id parsed from titles like Auftrags-Nr. cbn4sv9bdx (ID: #22999668) and from conversation_relations.
  • issue_categories removed from webhook — routing happens entirely in n8n.
  • Cached messages: POST /workflow/generate accepts optional cached_messages from the UI to skip a second full Plenty history fetch.
  • Attachment proxy for n8n: GET /webhooks/n8n/attachments/{message_uuid} and .../{filename} with X-API-KEY (Plenty ZIP extracted server-side).

Tickets — n8n callback & PDF attachments

  • Callback accepts optional attachments array (name, contentType, content_base64).
  • Stored on tickets.ai_response_attachments (JSON text) until send; UI shows attachment chips without exposing base64.
  • Send to Plenty includes attachments in the messenger POST payload.
  • JSON-string coercion for attachments when n8n sends the array as a string (common HTTP Request quirk).

Tickets — WebSocket live draft updates

  • Endpoints: /ws and /api/v1/tickets/ws (public, no JWT).
  • Broadcast on: workflow generate start (generating), n8n callback (draft / error), trigger failures.
  • Message: { "type": "ai_draft_update", "ticket_uuid": "...", "draft": { ... } }.
  • Frontend ticketAiDraft.js subscribes once; TicketsTab applies updates without interval polling.

Tickets — UI & categories

  • Left column: inbound customer messages only (from.type=user outbound filtered).
  • Right column: AI draft per message; category dropdown (12 issue types).
  • Recreate / Generate via n8n with confirmation when replacing an existing draft.
  • Optimistic generating state; final content arrives via WebSocket.

Tickets — data sync & training

  • ticket_message_responses — per-message Plenty/dashboard/n8n replies (optional table; graceful skip if not migrated).
  • closed_ticket_message_pairs — minimal training rows on ticket close (message_title, message_text, ai_response, ai_category).
  • tickets.ai_category column for manual and n8n-assigned complaint types.

Tickets — Plenty send fixes

  • create_reply_message() — POST /rest/messages with Plenty UI linkedTo shape (user/contact/email/order slots).
  • Re-query ticket after async Plenty calls (fixes detached SQLAlchemy session on generate/close/send).
  • Reopen restores ticket from Plenty when removed from DB on refresh.

Documentation

  • docs/docs/services/service_tickets/n8n-workflow.md — full API, callback, attachments, Code node examples.
  • docs/docs/services/service_tickets/n8n-agent-prompts.md — routing agent + 6 Fach-Agenten (Deutsch), tool specs, skeptical damaged-goods verification rules.
  • docs/docs/services/service_tickets/index.md — service overview and doc links.
  • Removed duplicate backend/service_tickets/docs/n8n-workflow.md (content lives under docs/).

🐛 Bug Fixes

  • Shop replies in conversation payloadnewReplyFromUser no longer sent to n8n as fake inbound messages; paired under ai_response only.
  • Generate 500Instance '<Ticket>' is not persistent after async Plenty calls; ticket re-queried after await.
  • Category update — skipped ticket_message_responses queries when table missing; avoids poisoned transactions.
  • 422 on n8n callback attachments — Pydantic rejected stringified JSON arrays; coercion added.
  • Undo reopen 404 — ticket re-imported from Plenty when missing locally after refresh.

📁 Files changed

Backend (service_tickets)

  • app/services/n8n_workflow_payload.py — lean payload, order IDs, shop-message filter.
  • app/services/ticket_order_context.pyexternal_order_id / order_id extraction.
  • app/services/ai_response_attachments.py — normalize, store, Plenty forward.
  • app/services/ticket_ws.py — WebSocket manager + broadcast.
  • app/services/message_response_store.py, message_response_sync.py — per-message sync.
  • app/services/closed_ticket_training.py — training pairs on close.
  • app/services/ticket_issue_categories.py — 12 category keys.
  • app/services/plenty/plenty_manager.py — UI-shaped replies, attachment enrich.
  • app/services/plenty_attachment_proxy.py, plenty/attachments.py — n8n attachment proxy.
  • app/api/v1/endpoints/tickets.py — generate, send, categories, cached messages, WS notify hooks.
  • app/api/v1/endpoints/n8n_webhooks.py — callback + attachments + WS notify.
  • app/main.py — WebSocket endpoints.

Frontend

  • src/pages/Tickets/Tabs/TicketsTab.jsx — inbound filter, categories, WS updates, attachment chips.
  • src/services/ws/ticketAiDraft.js — WebSocket client.
  • src/services/api/tickets/tickets.js — cached messages, category API.
  • src/utils/ticketIssueCategories.js, n8nWorkflowDefaults.js.
  • src/pages/Tickets/Credentials/WorkflowInfo.jsx — settings UI improvements.

Tests

  • test_n8n_workflow_payload.py, test_ticket_order_context.py, test_ai_response_attachments.py
  • test_message_response_store.py, test_closed_ticket_training.py, test_ticket_issue_categories.py
  • test_plenty_reply_payload.py, test_plenty_attachments.py

Docs

  • docs/docs/services/service_tickets/*
  • docs/docs/patchnotes/1.7/1.7.5.md

🔧 Database & SQL

Run on server before deploy (combined script):

-- See docker/postgres/migrations/add_tickets_ai_schema.sql
ALTER TABLE public.tickets ADD COLUMN IF NOT EXISTS ai_category text;
ALTER TABLE public.tickets ADD COLUMN IF NOT EXISTS ai_response_attachments text;

-- Per-message responses (optional, for UI sync)
-- ticket_message_responses table — see migration file

-- Closed-ticket training corpus
-- closed_ticket_message_pairs table — see migration file

Individual migrations:

  • docker/postgres/migrations/add_tickets_ai_schema.sql (combined)
  • docker/postgres/migrations/add_ticket_ai_response_attachments.sql
  • docker/postgres/migrations/add_ticket_message_responses.sql
  • docker/postgres/migrations/add_closed_ticket_message_pairs.sql

Usage notes

Tickets workflow

  1. Run SQL migrations on Postgres.
  2. Credentials → Plenty + n8n Workflow configured.
  3. Expand ticket → Generate via n8n → draft appears via WebSocket (no polling).
  4. Edit draft → Send to Plenty.

n8n callback (text only)

{
  "action": "generate_complete",
  "ticket_uuid": "<from webhook>",
  "message_uuid": "<from webhook>",
  "content": "<German reply, Sie-Form>"
}

n8n callback (with PDF) — optional attachments with content_base64; omit when no PDF.

n8n Code node — build body in JavaScript; use output.response from agent nodes; see n8n-workflow.md.

WebSocket / nginx

  • Proxy /api/v1/tickets/ws with WebSocket upgrade headers in production.
  • Dev: frontend connects to localhost:8006 (VITE_TICKETS_API_PORT).

Agent prompts

  • Copy system prompts from n8n-agent-prompts.md into n8n LLM nodes.
  • Damaged-article agent: skeptical photo verification before any refund promise.