From b0d1e5299d985714728666352f1061fbfce1b415 Mon Sep 17 00:00:00 2001 From: Will Freeman Date: Thu, 23 Apr 2026 09:43:18 -0600 Subject: [PATCH] add customer before creating ticket --- api/services/ZammadClient.ts | 40 ++++++++++++++++++++++++++++++- webapp/src/services/apiService.ts | 2 +- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/api/services/ZammadClient.ts b/api/services/ZammadClient.ts index 39a533d..f1e5937 100644 --- a/api/services/ZammadClient.ts +++ b/api/services/ZammadClient.ts @@ -44,15 +44,53 @@ export interface CreateTicketPayload { } export class ZammadClient { + private async upsertCustomer(name: string, email: string): Promise { + const normalizedEmail = email.toLowerCase(); + + // Search for existing user by email + const searchResponse = await fetch( + `${ZAMMAD_URL}/api/v1/users/search?query=${encodeURIComponent(normalizedEmail)}&limit=1`, + { + headers: { 'Authorization': `Token token=${ZAMMAD_TOKEN}` }, + } + ); + + if (searchResponse.ok) { + const users = await searchResponse.json() as Array<{ id: number; email: string }>; + const match = users.find(u => u.email?.toLowerCase() === normalizedEmail); + if (match) return match.id; + } + + // Create the customer if not found + const createResponse = await fetch(`${ZAMMAD_URL}/api/v1/users`, { + method: 'POST', + headers: { + 'Authorization': `Token token=${ZAMMAD_TOKEN}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ firstname: name, email: normalizedEmail, roles: ['Customer'] }), + }); + + if (!createResponse.ok) { + const text = await createResponse.text(); + throw new Error(`Zammad customer creation failed: ${createResponse.status} ${text}`); + } + + const user = await createResponse.json() as { id: number }; + return user.id; + } + async createTicket(payload: CreateTicketPayload): Promise { const { name, email, topic, subject, message } = payload; const group = TOPIC_GROUP_MAP[topic]; + const customerId = await this.upsertCustomer(name, email); + const body = JSON.stringify({ title: subject, group, priority: topic === 'media' ? '3 high' : '2 normal', - customer: email, + customer_id: customerId, article: { subject, body: message, diff --git a/webapp/src/services/apiService.ts b/webapp/src/services/apiService.ts index 2d0247e..4b2f16d 100644 --- a/webapp/src/services/apiService.ts +++ b/webapp/src/services/apiService.ts @@ -48,7 +48,7 @@ export class BoundingBox implements BoundingBoxLiteral { } const apiService = axios.create({ - baseURL: window.location.hostname === "localhost" ? "http://localhost:3000" : "https://api.deflock.org", + baseURL: window.location.hostname === "localhost" ? "http://localhost:3420" : "https://api.deflock.org", headers: { "Content-Type": "application/json", },