Files
livedash-node/prisma/schema.prisma
Max Kowalski 5c1ced5900 feat: add rawTranscriptContent field to SessionImport model
feat: enhance server initialization with environment validation and import processing scheduler

test: add Jest setup for unit tests and mock console methods

test: implement unit tests for environment management and validation

test: create unit tests for transcript fetcher functionality
2025-06-27 19:00:22 +02:00

190 lines
4.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite" // still OK for local/dev; use Postgres in prod
url = "file:./dev.db"
}
/**
* ENUMS fewer magic strings
*/
enum UserRole {
ADMIN
USER
AUDITOR
}
enum SentimentCategory {
POSITIVE
NEUTRAL
NEGATIVE
}
/**
* COMPANY (multi-tenant root)
*/
model Company {
id String @id @default(uuid())
name String
csvUrl String
csvUsername String?
csvPassword String?
sentimentAlert Float?
dashboardOpts Json? // JSON column instead of opaque string
users User[] @relation("CompanyUsers")
sessions Session[]
imports SessionImport[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
/**
* USER (auth accounts)
*/
model User {
id String @id @default(uuid())
email String @unique
password String
role UserRole @default(USER)
company Company @relation("CompanyUsers", fields: [companyId], references: [id], onDelete: Cascade)
companyId String
resetToken String?
resetTokenExpiry DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
/**
* SESSION ↔ SESSIONIMPORT (1-to-1)
*/
/**
* 1. Normalised session ---------------------------
*/
model Session {
id String @id @default(uuid())
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
companyId String
/**
* 1-to-1 link back to the import row
*/
import SessionImport? @relation("ImportToSession", fields: [importId], references: [id])
importId String? @unique
/**
* session-level data (processed from SessionImport)
*/
startTime DateTime
endTime DateTime
// Processed fields from SessionImport data
ipAddress String?
country String? // processed from countryCode
language String? // processed from language
messagesSent Int?
sentiment Float? // processed from sentimentRaw
sentimentCategory SentimentCategory?
escalated Boolean?
forwardedHr Boolean?
fullTranscriptUrl String?
avgResponseTime Float? // processed from avgResponseTimeSeconds
tokens Int?
tokensEur Float?
category String?
initialMsg String? // processed from initialMessage
// Processing metadata
processed Boolean @default(false)
questions String? // JSON array of extracted questions
summary String? // AI-generated summary
/**
* ---------- the missing opposite side ----------
*/
messages Message[] // <-- satisfies Message.session
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([companyId, startTime])
}
/**
* 2. Raw CSV row waiting to be processed ----------
*/
enum ImportStatus {
QUEUED
PROCESSING
DONE
ERROR
}
model SessionImport {
id String @id @default(uuid())
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
companyId String
/**
* 1-to-1 back-relation; NO fields/references here
*/
session Session? @relation("ImportToSession")
// ─── 16 CSV columns 1-to-1 ────────────────────────
externalSessionId String @unique // value from CSV column 1
startTimeRaw String
endTimeRaw String
ipAddress String?
countryCode String?
language String?
messagesSent Int?
sentimentRaw String?
escalatedRaw String?
forwardedHrRaw String?
fullTranscriptUrl String?
avgResponseTimeSeconds Float?
tokens Int?
tokensEur Float?
category String?
initialMessage String?
// ─── Raw transcript content ─────────────────────────
rawTranscriptContent String? // Fetched content from fullTranscriptUrl
// ─── bookkeeping ─────────────────────────────────
status ImportStatus @default(QUEUED)
errorMsg String?
processedAt DateTime?
createdAt DateTime @default(now())
@@unique([companyId, externalSessionId]) // idempotent re-imports
@@index([status])
}
/**
* MESSAGE (individual lines)
*/
model Message {
id String @id @default(uuid())
session Session @relation(fields: [sessionId], references: [id], onDelete: Cascade)
sessionId String
timestamp DateTime?
role String // "user" | "assistant" | "system" free-form keeps migration easy
content String
order Int
createdAt DateTime @default(now())
@@unique([sessionId, order]) // guards against duplicate order values
@@index([sessionId, order])
}