Daily Report – 21. März 2026
CRM Pipeline-Ansicht, CSV-Import & Ticket E-Mail-Reply
CRM – Pipeline-Ansicht (Kanban)
Backend
Alembic Migration a1b2c3d4e5f7: pipeline_stage VARCHAR(50) DEFAULT 'new_lead' an customers-Tabelle + Index
PipelineStage Enum: new_lead → qualified → proposal → negotiation → won | lost
get_pipeline_customers(db) → gruppiert alle Kunden nach Stage
update_pipeline_stage(db, customer_id, stage) → Stage-Wechsel
GET /backoffice/crm/pipeline — Pipeline-Daten (stage → Kunden)
PATCH /backoffice/crm/customers/{id}/pipeline-stage — Stage updaten
Frontend
PipelineStage Type + pipeline_stage am Customer-Interface
crm.service.ts: getPipeline(), updatePipelineStage()
useCustomers.ts: loadPipeline(), optimistisches Stage-Update
useCrmNavigation.ts: View "pipeline" + goPipeline()
Neue Seite CrmPipelinePage.vue: 6-Spalten-Kanban, natives HTML5 Drag & Drop (kein externes Package), Farb-Kodierung je Stage, Trophy/Ban-Quickaction-Buttons
CrmApp.vue: Pipeline-View eingebunden
CustomersListPage.vue: “Pipeline”-Button im Header
CRM – CSV-Import
Backend
Neue Datei csv_import.py: import_customers_csv(db, file_bytes, skip_duplicates, dry_run)
Auto-Delimiter-Erkennung (; oder ,)
Encoding-Fallback (UTF-8-SIG → Latin-1)
Pflichtfeld-Validierung (name)
Duplikaterkennung per E-Mail
Rückgabe: ImportResult(imported, skipped, errors, preview)
POST /backoffice/crm/customers/import-csv mit dry_run und skip_duplicates Query-Params
CsvImportResponse Schema
Frontend
CsvImportResult Interface in customer.ts
crm.service.ts: importCsvDryRun(), importCsv()
CustomersListPage.vue: 3-Schritt-Import-Modal
Step 1: Datei-Upload (Drag & Drop + File-Picker)
Step 2: Vorschau der ersten 5 Zeilen (dry_run=true)
Step 3: Bestätigung mit Import-Zusammenfassung
Support – Ticket E-Mail-Reply
Backend
Alembic Migration b2c3d4e5f6a7: reporter_email VARCHAR(255) an support_tickets
reporter_email Feld am Support-Ticket-Model + Schemas (TicketCreate, TicketUpdate, TicketResponse)
TicketReplyRequest Schema (body: str)
send_ticket_reply() Funktion im EmailService (Jinja2-Templates ticket_reply.html / .txt)
POST /api/support/tickets/{id}/reply:
Prüft ob reporter_email vorhanden
Sendet E-Mail via SMTP
Speichert Antwort als öffentlichen Kommentar
email_intake/service.py: trägt reporter_email beim automatischen Ticket-Erstellen ein
Frontend
TicketDetailPage.vue: reporterEmail Computed (DB-Feld + Regex-Fallback aus mailto-Link)
Reply-Modal: Fehlerhinweis (replyError), Erfolgs-Banner (replySent), Send-Button deaktiviert ohne E-Mail
Produktions-Deploy-Fix
backend/entrypoint.prod.sh: führt alembic upgrade head vor uvicorn aus
backend/Dockerfile.prod: entrypoint statt CMD, healthcheck start-period auf 60s erhöht
.github/workflows/deploy-production.yml: expliziter Migrations-Schritt nach Container-Start
Commits
Hash
Beschreibung
1e691ca
DATEV-Export (EXTF Buchungsstapel)
c74f5cf
Mahnwesen (Dunning) mit 3 Mahnstufen
3c8aa80
Rechnung per E-Mail direkt aus WorkmateOS
abd8bfe
Email-Design auf K.I.T. Rebrand 2026
afac7e8
SMTP Credentials als GitHub Secrets
(heute)
CRM Pipeline + CSV-Import + Ticket Reply + Deploy-Fix