CognxSafeTrack
feat: backlog P0→P3 — toast system, payments, tenant isolation, feedback handler, i18n parity
6dd9bad | import { prisma } from './prisma'; | |
| import { whatsappQueue } from './queue'; | |
| export class KBService { | |
| static async uploadAndIndex(organizationId: string, fileBuffer: Buffer, filename: string, mimeType: string) { | |
| const { uploadFile } = await import('./storage'); | |
| const publicUrl = await uploadFile(fileBuffer, filename, mimeType, organizationId); | |
| await prisma.organization.update({ | |
| where: { id: organizationId }, | |
| data: { knowledgeBaseUrl: publicUrl } | |
| }); | |
| await whatsappQueue.add('process-kb', { organizationId, url: publicUrl }); | |
| const chunkCount = await prisma.knowledgeBaseEntry.count({ where: { organizationId } }); | |
| return { publicUrl, chunkCount }; | |
| } | |
| static async getStats(organizationId: string) { | |
| const [chunkCount, org] = await Promise.all([ | |
| prisma.knowledgeBaseEntry.count({ where: { organizationId } }), | |
| prisma.organization.findUnique({ where: { id: organizationId }, select: { knowledgeBaseUrl: true } }) | |
| ]); | |
| return { chunkCount, hasKnowledgeBase: !!org?.knowledgeBaseUrl, knowledgeBaseUrl: org?.knowledgeBaseUrl }; | |
| } | |
| static async listChunks(organizationId: string, page: number, limit: number) { | |
| const skip = (page - 1) * limit; | |
| const [entries, total] = await Promise.all([ | |
| prisma.knowledgeBaseEntry.findMany({ | |
| where: { organizationId }, | |
| orderBy: { createdAt: 'desc' }, | |
| skip, | |
| take: limit, | |
| select: { id: true, content: true, metadata: true, createdAt: true } | |
| }), | |
| prisma.knowledgeBaseEntry.count({ where: { organizationId } }) | |
| ]); | |
| return { entries, total, page, limit }; | |
| } | |
| static async deleteChunk(organizationId: string, entryId: string) { | |
| const entry = await prisma.knowledgeBaseEntry.findFirst({ where: { id: entryId, organizationId } }); | |
| if (!entry) return false; | |
| await prisma.knowledgeBaseEntry.delete({ where: { id: entryId } }); | |
| return true; | |
| } | |
| } | |