Added Backend

This commit is contained in:
2026-01-06 12:07:43 +01:00
parent b013ef8f4b
commit 6f3d4c0bff
165 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
// modules/helpdesk/helpdesk.inbound.routes.ts
import { FastifyPluginAsync } from 'fastify'
import { createConversation } from '../modules/helpdesk/helpdesk.conversation.service.js'
import { addMessage } from '../modules/helpdesk/helpdesk.message.service.js'
import { getOrCreateContact } from '../modules/helpdesk/helpdesk.contact.service.js'
/**
* Öffentliche Route zum Empfang eingehender Kontaktformular-Nachrichten.
* Authentifizierung: über `public_token` aus helpdesk_channel_instances
*/
function extractDomain(email) {
if (!email) return null
const parts = email.split("@")
return parts.length === 2 ? parts[1].toLowerCase() : null
}
async function findCustomerOrContactByEmailOrDomain(server,fromMail, tenantId) {
const sender = fromMail
const senderDomain = extractDomain(sender)
if (!senderDomain) return null
// 1⃣ Direkter Match über contacts
const { data: contactMatch } = await server.supabase
.from("contacts")
.select("id, customer")
.eq("email", sender)
.eq("tenant", tenantId)
.maybeSingle()
if (contactMatch?.customer_id) return {
customer: contactMatch.customer,
contact: contactMatch.id
}
// 2⃣ Kunden laden, bei denen E-Mail oder Rechnungsmail passt
const { data: customers, error } = await server.supabase
.from("customers")
.select("id, infoData")
.eq("tenant", tenantId)
if (error) {
console.error(`[Helpdesk] Fehler beim Laden der Kunden:`, error.message)
return null
}
// 3⃣ Durch Kunden iterieren und prüfen
for (const c of customers || []) {
const info = c.infoData || {}
const email = info.email?.toLowerCase()
const invoiceEmail = info.invoiceEmail?.toLowerCase()
const emailDomain = extractDomain(email)
const invoiceDomain = extractDomain(invoiceEmail)
// exakter Match oder Domain-Match
if (
sender === email ||
sender === invoiceEmail ||
senderDomain === emailDomain ||
senderDomain === invoiceDomain
) {
return {customer: c.id, contact:null}
}
}
return null
}
const helpdeskInboundRoutes: FastifyPluginAsync = async (server) => {
// Öffentliche POST-Route
server.post('/helpdesk/inbound/:public_token', async (req, res) => {
const { public_token } = req.params as { public_token: string }
const { email, phone, display_name, subject, message } = req.body as {
email: string,
phone: string,
display_name: string
subject: string
message: string
}
if (!message) {
return res.status(400).send({ error: 'Message content required' })
}
// 1⃣ Kanalinstanz anhand des Tokens ermitteln
const { data: channel, error: channelError } = await server.supabase
.from('helpdesk_channel_instances')
.select('*')
.eq('public_token', public_token)
.single()
if (channelError || !channel) {
return res.status(404).send({ error: 'Invalid channel token' })
}
const tenant_id = channel.tenant_id
const channel_instance_id = channel.id
// @ts-ignore
const {customer, contact: contactPerson} = await findCustomerOrContactByEmailOrDomain(server,email, tenant_id )
// 2⃣ Kontakt finden oder anlegen
const contact = await getOrCreateContact(server, tenant_id, {
email,
phone,
display_name,
customer_id: customer,
contact_id: contactPerson,
})
// 3⃣ Konversation erstellen
const conversation = await createConversation(server, {
tenant_id,
contact,
channel_instance_id,
subject: subject ?? 'Kontaktformular Anfrage',
customer_id: customer,
contact_person_id: contactPerson
})
// 4⃣ Erste Nachricht hinzufügen
await addMessage(server, {
tenant_id,
conversation_id: conversation.id,
direction: 'incoming',
payload: { type: 'text', text: message },
raw_meta: { source: 'contact_form' },
})
// (optional) Auto-Antwort oder Event hier ergänzen
return res.status(201).send({
success: true,
conversation_id: conversation.id,
})
})
}
export default helpdeskInboundRoutes