crm-system/prisma/schema.prisma

228 lines
6.5 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model DbHealthCheck {
id String @id @default(uuid())
createdAt DateTime @default(now())
}
// =============================================================================
// Пользователи и роли (RBAC)
// =============================================================================
enum Role {
ADMIN
DIRECTOR
MECHANIC
WORKER
OTHER
}
model User {
id String @id @default(uuid())
email String @unique
password String // bcrypt hash
firstName String
lastName String
role Role @default(OTHER)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
assignedToOrders RepairOrderAssignee[]
}
// =============================================================================
// Контрагенты
// =============================================================================
model Contractor {
id String @id @default(uuid())
name String
inn String? // ИНН (опционально)
address String?
phone String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
repairOrders RepairOrder[]
trips Trip[]
serviceObjects ServiceObject[]
calculationTemplates CalculationTemplate[]
}
// =============================================================================
// Агрегаты (оборудование)
// =============================================================================
model Unit {
id String @id @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
identifiers UnitIdentifier[]
repairOrders RepairOrder[]
}
model UnitIdentifier {
id String @id @default(uuid())
unitId String
type String // 'SERIAL', 'INTERNAL', 'CUSTOMER'
value String
validFrom DateTime @default(now())
validTo DateTime?
// Relations
unit Unit @relation(fields: [unitId], references: [id], onDelete: Cascade)
@@unique([unitId, type, value, validFrom])
}
// =============================================================================
// Ремонты (RepairOrder)
// =============================================================================
enum RepairStatus {
RECEIVED
DIAGNOSIS
WAITING_APPROVAL
WAITING_PARTS
IN_WORK
ISSUED
CANCELED
}
model RepairOrder {
id String @id @default(uuid())
unitId String
contractorId String
status RepairStatus @default(RECEIVED)
description String?
issuedAt DateTime? // дата выдачи
warrantyFrom DateTime? // начало гарантии
warrantyTo DateTime? // конец гарантии
warrantyDays Int? // срок гарантии в днях
version Int @default(1) // optimistic locking
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
unit Unit @relation(fields: [unitId], references: [id])
contractor Contractor @relation(fields: [contractorId], references: [id])
assignees RepairOrderAssignee[]
calculation Calculation?
@@index([status])
@@index([contractorId])
@@index([unitId])
}
model RepairOrderAssignee {
id String @id @default(uuid())
repairOrderId String
userId String
assignedAt DateTime @default(now())
// Relations
repairOrder RepairOrder @relation(fields: [repairOrderId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([repairOrderId, userId])
}
// =============================================================================
// Выезды
// =============================================================================
model Trip {
id String @id @default(uuid())
contractorId String
serviceObjectId String?
description String?
scheduledFor DateTime
completedAt DateTime?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
contractor Contractor @relation(fields: [contractorId], references: [id])
serviceObject ServiceObject? @relation(fields: [serviceObjectId], references: [id])
@@index([scheduledFor])
}
model ServiceObject {
id String @id @default(uuid())
contractorId String
name String
address String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
contractor Contractor @relation(fields: [contractorId], references: [id])
trips Trip[]
}
// =============================================================================
// Калькуляции (MVP без денег)
// =============================================================================
model Calculation {
id String @id @default(uuid())
repairOrderId String @unique
templateId String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
repairOrder RepairOrder @relation(fields: [repairOrderId], references: [id], onDelete: Cascade)
template CalculationTemplate? @relation(fields: [templateId], references: [id])
items CalculationItem[]
}
model CalculationTemplate {
id String @id @default(uuid())
contractorId String?
name String
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
contractor Contractor? @relation(fields: [contractorId], references: [id])
calculations Calculation[]
}
model CalculationItem {
id String @id @default(uuid())
calculationId String
type String // 'WORK' or 'MATERIAL'
name String
quantity Float
unit String // единицы измерения
price Float? // отложено на будущее (MVP без денег)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
calculation Calculation @relation(fields: [calculationId], references: [id], onDelete: Cascade)
@@index([calculationId, type])
}