// 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, } }