Files
FEDEO/backend/src/modules/helpdesk/helpdesk.conversation.service.ts

124 lines
4.0 KiB
TypeScript

// modules/helpdesk/helpdesk.conversation.service.ts
import { FastifyInstance } from 'fastify'
import { getOrCreateContact } from './helpdesk.contact.service.js'
import {useNextNumberRangeNumber} from "../../utils/functions";
import { and, desc, eq } from "drizzle-orm";
import { customers, helpdesk_contacts, helpdesk_conversations } from "../../../db/schema";
export async function createConversation(
server: FastifyInstance,
{
tenant_id,
contact,
channel_instance_id,
subject,
customer_id = null,
contact_person_id = null,
}: {
tenant_id: number
contact: { email?: string; phone?: string; display_name?: string }
channel_instance_id: string
subject?: string,
customer_id?: number,
contact_person_id?: number
}
) {
const contactRecord = await getOrCreateContact(server, tenant_id, contact)
const {usedNumber } = await useNextNumberRangeNumber(server, tenant_id, "tickets")
const inserted = await server.db
.insert(helpdesk_conversations)
.values({
tenantId: tenant_id,
contactId: contactRecord.id,
channelInstanceId: channel_instance_id,
subject: subject || null,
status: 'open',
createdAt: new Date(),
customerId: customer_id,
contactPersonId: contact_person_id,
ticketNumber: usedNumber
})
.returning()
const data = inserted[0]
return {
...data,
channel_instance_id: data.channelInstanceId,
contact_id: data.contactId,
contact_person_id: data.contactPersonId,
created_at: data.createdAt,
customer_id: data.customerId,
last_message_at: data.lastMessageAt,
tenant_id: data.tenantId,
ticket_number: data.ticketNumber,
}
}
export async function getConversations(
server: FastifyInstance,
tenant_id: number,
opts?: { status?: string; limit?: number }
) {
const { status, limit = 50 } = opts || {}
const filters = [eq(helpdesk_conversations.tenantId, tenant_id)]
if (status) filters.push(eq(helpdesk_conversations.status, status))
const data = await server.db
.select({
conversation: helpdesk_conversations,
contact: helpdesk_contacts,
customer: customers,
})
.from(helpdesk_conversations)
.leftJoin(helpdesk_contacts, eq(helpdesk_contacts.id, helpdesk_conversations.contactId))
.leftJoin(customers, eq(customers.id, helpdesk_conversations.customerId))
.where(and(...filters))
.orderBy(desc(helpdesk_conversations.lastMessageAt))
.limit(limit)
return data.map((entry) => ({
...entry.conversation,
helpdesk_contacts: entry.contact,
channel_instance_id: entry.conversation.channelInstanceId,
contact_id: entry.conversation.contactId,
contact_person_id: entry.conversation.contactPersonId,
created_at: entry.conversation.createdAt,
customer_id: entry.customer,
last_message_at: entry.conversation.lastMessageAt,
tenant_id: entry.conversation.tenantId,
ticket_number: entry.conversation.ticketNumber,
}))
}
export async function updateConversationStatus(
server: FastifyInstance,
conversation_id: string,
status: string
) {
const valid = ['open', 'in_progress', 'waiting_for_customer', 'answered', 'closed']
if (!valid.includes(status)) throw new Error('Invalid status')
const updated = await server.db
.update(helpdesk_conversations)
.set({ status })
.where(eq(helpdesk_conversations.id, conversation_id))
.returning()
const data = updated[0]
return {
...data,
channel_instance_id: data.channelInstanceId,
contact_id: data.contactId,
contact_person_id: data.contactPersonId,
created_at: data.createdAt,
customer_id: data.customerId,
last_message_at: data.lastMessageAt,
tenant_id: data.tenantId,
ticket_number: data.ticketNumber,
}
}