generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ==================== USER ROLES (dynamicke) ==================== model UserRole { id String @id @default(cuid()) code String @unique name String description String? permissions Json level Int order Int @default(0) active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt users User[] @@index([active]) @@index([level]) } // ==================== USERS ==================== model User { id String @id @default(cuid()) email String @unique password String name String roleId String role UserRole @relation(fields: [roleId], references: [id]) active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt ownedProjects Project[] @relation("ProjectOwner") assignedProjects ProjectMember[] createdTasks Task[] @relation("TaskCreator") assignedTasks TaskAssignee[] reminders Reminder[] activityLogs ActivityLog[] createdEquipment Equipment[] @relation("EquipmentCreator") performedRevisions Revision[] uploadedEquipmentFiles EquipmentAttachment[] assignedRMAs RMA[] @relation("RMAAssignee") createdRMAs RMA[] @relation("RMACreator") approvedRMAs RMA[] @relation("RMAApprover") rmaAttachments RMAAttachment[] rmaStatusChanges RMAStatusHistory[] rmaComments RMAComment[] taskComments Comment[] taskAttachments TaskAttachment[] @relation("TaskAttachmentUploader") createdCustomers Customer[] @@index([email]) @@index([roleId]) @@index([active]) } // ==================== CONFIGURATION TABLES ==================== model EquipmentType { id String @id @default(cuid()) code String @unique name String description String? color String? icon String? order Int @default(0) active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt equipment Equipment[] @@index([active]) @@index([order]) } model RevisionType { id String @id @default(cuid()) code String @unique name String intervalDays Int reminderDays Int @default(14) color String? description String? order Int @default(0) active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt revisions Revision[] @@index([active]) @@index([order]) } model RMAStatus { id String @id @default(cuid()) code String @unique name String description String? color String? icon String? order Int @default(0) isInitial Boolean @default(false) isFinal Boolean @default(false) canTransitionTo Json? active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt rmas RMA[] @@index([active]) @@index([order]) @@index([isInitial]) @@index([isFinal]) } model RMASolution { id String @id @default(cuid()) code String @unique name String description String? color String? order Int @default(0) active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt rmas RMA[] @@index([active]) @@index([order]) } model TaskStatus { id String @id @default(cuid()) code String @unique name String description String? color String? icon String? order Int @default(0) swimlaneColumn String? isInitial Boolean @default(false) isFinal Boolean @default(false) canTransitionTo Json? active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt tasks Task[] projects Project[] @@index([active]) @@index([swimlaneColumn]) @@index([order]) } model Priority { id String @id @default(cuid()) code String @unique name String description String? color String? icon String? level Int order Int @default(0) active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt tasks Task[] @@index([active]) @@index([level]) @@index([order]) } model Tag { id String @id @default(cuid()) code String @unique name String description String? color String? entityType String order Int @default(0) active Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt projectTags ProjectTag[] taskTags TaskTag[] equipmentTags EquipmentTag[] rmaTags RMATag[] @@index([entityType]) @@index([active]) } model SystemSetting { id String @id @default(cuid()) key String @unique value Json category String label String description String? dataType String validation Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([category]) } // ==================== CUSTOMERS ==================== model Customer { id String @id @default(cuid()) name String address String? email String? phone String? ico String? dic String? icdph String? contactPerson String? contactEmail String? contactPhone String? externalId String? @unique externalSource String? notes String? active Boolean @default(true) createdById String createdBy User @relation(fields: [createdById], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt projects Project[] equipment Equipment[] rmas RMA[] @@index([name]) @@index([ico]) @@index([externalId]) @@index([active]) } // ==================== PROJECTS ==================== model Project { id String @id @default(cuid()) name String description String? customerId String? customer Customer? @relation(fields: [customerId], references: [id]) ownerId String owner User @relation("ProjectOwner", fields: [ownerId], references: [id]) statusId String status TaskStatus @relation(fields: [statusId], references: [id]) softDeadline DateTime? hardDeadline DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt completedAt DateTime? tasks Task[] members ProjectMember[] tags ProjectTag[] @@index([ownerId]) @@index([statusId]) @@index([customerId]) @@index([hardDeadline]) } model ProjectMember { id String @id @default(cuid()) projectId String userId String project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) addedAt DateTime @default(now()) @@unique([projectId, userId]) @@index([projectId]) @@index([userId]) } model ProjectTag { projectId String tagId String project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade) @@id([projectId, tagId]) } // ==================== TASKS ==================== model Task { id String @id @default(cuid()) title String description String? projectId String? project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade) parentId String? parent Task? @relation("SubTasks", fields: [parentId], references: [id], onDelete: Cascade) subTasks Task[] @relation("SubTasks") statusId String status TaskStatus @relation(fields: [statusId], references: [id]) priorityId String priority Priority @relation(fields: [priorityId], references: [id]) deadline DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt completedAt DateTime? createdById String createdBy User @relation("TaskCreator", fields: [createdById], references: [id]) assignees TaskAssignee[] reminders Reminder[] comments Comment[] tags TaskTag[] attachments TaskAttachment[] @@index([projectId]) @@index([parentId]) @@index([statusId]) @@index([priorityId]) @@index([deadline]) @@index([createdById]) } model TaskAssignee { id String @id @default(cuid()) taskId String userId String task Task @relation(fields: [taskId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) assignedAt DateTime @default(now()) @@unique([taskId, userId]) @@index([taskId]) @@index([userId]) } model TaskTag { taskId String tagId String task Task @relation(fields: [taskId], references: [id], onDelete: Cascade) tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade) @@id([taskId, tagId]) } model TaskAttachment { id String @id @default(cuid()) taskId String task Task @relation(fields: [taskId], references: [id], onDelete: Cascade) filename String filepath String mimetype String size Int uploadedById String uploadedBy User @relation("TaskAttachmentUploader", fields: [uploadedById], references: [id]) uploadedAt DateTime @default(now()) @@index([taskId]) } model Reminder { id String @id @default(cuid()) taskId String userId String task Task @relation(fields: [taskId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) remindAt DateTime snoozedUntil DateTime? dismissed Boolean @default(false) message String? createdAt DateTime @default(now()) @@index([userId, remindAt]) @@index([taskId]) } model Comment { id String @id @default(cuid()) taskId String userId String task Task @relation(fields: [taskId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id]) content String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([taskId]) @@index([userId]) @@index([createdAt]) } // ==================== EQUIPMENT MANAGEMENT ==================== model Equipment { id String @id @default(cuid()) name String typeId String type EquipmentType @relation(fields: [typeId], references: [id]) brand String? model String? customerId String? customer Customer? @relation(fields: [customerId], references: [id]) address String location String? partNumber String? serialNumber String? installDate DateTime? warrantyEnd DateTime? warrantyStatus String? description String? notes String? active Boolean @default(true) createdById String createdBy User @relation("EquipmentCreator", fields: [createdById], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt revisions Revision[] attachments EquipmentAttachment[] tags EquipmentTag[] @@index([typeId]) @@index([customerId]) @@index([warrantyEnd]) @@index([active]) @@index([createdById]) } model Revision { id String @id @default(cuid()) equipmentId String equipment Equipment @relation(fields: [equipmentId], references: [id], onDelete: Cascade) typeId String type RevisionType @relation(fields: [typeId], references: [id]) performedDate DateTime nextDueDate DateTime? performedById String performedBy User @relation(fields: [performedById], references: [id]) findings String? result String? notes String? reminderSent Boolean @default(false) reminderDate DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([equipmentId]) @@index([typeId]) @@index([performedById]) @@index([nextDueDate]) @@index([reminderDate]) } model EquipmentAttachment { id String @id @default(cuid()) equipmentId String equipment Equipment @relation(fields: [equipmentId], references: [id], onDelete: Cascade) filename String filepath String mimetype String size Int uploadedById String uploadedBy User @relation(fields: [uploadedById], references: [id]) uploadedAt DateTime @default(now()) @@index([equipmentId]) } model EquipmentTag { equipmentId String tagId String equipment Equipment @relation(fields: [equipmentId], references: [id], onDelete: Cascade) tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade) @@id([equipmentId, tagId]) } // ==================== RMA (REKLAMACIE) ==================== model RMA { id String @id @default(cuid()) rmaNumber String @unique customerId String? customer Customer? @relation(fields: [customerId], references: [id]) customerName String? customerAddress String? customerEmail String? customerPhone String? customerICO String? submittedBy String productName String invoiceNumber String? purchaseDate DateTime? productNumber String? serialNumber String? accessories String? issueDescription String statusId String status RMAStatus @relation(fields: [statusId], references: [id]) proposedSolutionId String? proposedSolution RMASolution? @relation(fields: [proposedSolutionId], references: [id]) requiresApproval Boolean @default(false) approvedById String? approvedBy User? @relation("RMAApprover", fields: [approvedById], references: [id]) approvedAt DateTime? receivedDate DateTime? receivedLocation String? internalNotes String? resolutionDate DateTime? resolutionNotes String? assignedToId String? assignedTo User? @relation("RMAAssignee", fields: [assignedToId], references: [id]) createdById String createdBy User @relation("RMACreator", fields: [createdById], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt closedAt DateTime? attachments RMAAttachment[] statusHistory RMAStatusHistory[] comments RMAComment[] tags RMATag[] @@index([rmaNumber]) @@index([customerId]) @@index([statusId]) @@index([proposedSolutionId]) @@index([assignedToId]) @@index([createdById]) @@index([purchaseDate]) @@index([receivedDate]) } model RMAAttachment { id String @id @default(cuid()) rmaId String rma RMA @relation(fields: [rmaId], references: [id], onDelete: Cascade) filename String filepath String mimetype String size Int uploadedById String uploadedBy User @relation(fields: [uploadedById], references: [id]) uploadedAt DateTime @default(now()) @@index([rmaId]) } model RMAStatusHistory { id String @id @default(cuid()) rmaId String rma RMA @relation(fields: [rmaId], references: [id], onDelete: Cascade) fromStatusId String? toStatusId String changedById String changedBy User @relation(fields: [changedById], references: [id]) notes String? changedAt DateTime @default(now()) @@index([rmaId]) @@index([changedAt]) } model RMAComment { id String @id @default(cuid()) rmaId String rma RMA @relation(fields: [rmaId], references: [id], onDelete: Cascade) content String userId String user User @relation(fields: [userId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([rmaId]) @@index([createdAt]) } model RMATag { rmaId String tagId String rma RMA @relation(fields: [rmaId], references: [id], onDelete: Cascade) tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade) @@id([rmaId, tagId]) } // ==================== ACTIVITY LOG ==================== model ActivityLog { id String @id @default(cuid()) userId String user User @relation(fields: [userId], references: [id]) action String entity String entityId String changes Json? ipAddress String? userAgent String? createdAt DateTime @default(now()) @@index([userId]) @@index([entity, entityId]) @@index([createdAt]) }