// AR-ProjectManagement — Prisma Schema // Base de datos: PostgreSQL 16 generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ============================================================ // ENUMS // ============================================================ enum Role { SUPER_ADMIN DIRECTOR GERENTE JEFE_AREA COLABORADOR FINANCIERO AUDITOR } enum ProjectStatus { ACTIVO PAUSADO COMPLETADO EN_RIESGO CANCELADO } enum TaskStatus { PENDIENTE EN_PROCESO BLOQUEADA EN_VERIFICACION NO_CONFORME APROBADO_TECNICO ACEPTADO_FORMAL COMPLETADA } enum Priority { CRITICO ALTO MEDIO BAJO } // ============================================================ // MODULO 1: USUARIOS Y AUTENTICACION // ============================================================ model User { id String @id @default(uuid()) email String @unique passwordHash String @map("password_hash") firstName String @map("first_name") lastName String @map("last_name") role Role @default(COLABORADOR) isActive Boolean @default(true) @map("is_active") isTwoFactorEnabled Boolean @default(false) @map("is_two_factor_enabled") twoFactorSecret String? @map("two_factor_secret") loginAttempts Int @default(0) @map("login_attempts") lockedUntil DateTime? @map("locked_until") lastLoginAt DateTime? @map("last_login_at") lastLoginIp String? @map("last_login_ip") avatarUrl String? @map("avatar_url") phone String? department String? jobTitle String? @map("job_title") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") refreshTokens RefreshToken[] auditLogs AuditLog[] projectMembers ProjectMember[] tasksAssigned Task[] @relation("TaskAssignee") tasksCreated Task[] @relation("TaskCreator") comments Comment[] @@map("users") } model RefreshToken { id String @id @default(uuid()) token String @unique userId String @map("user_id") expiresAt DateTime @map("expires_at") createdAt DateTime @default(now()) @map("created_at") revokedAt DateTime? @map("revoked_at") ipAddress String? @map("ip_address") userAgent String? @map("user_agent") user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@map("refresh_tokens") } // ============================================================ // LOG DE AUDITORIA INMUTABLE // ============================================================ model AuditLog { id String @id @default(uuid()) userId String? @map("user_id") action String entity String entityId String? @map("entity_id") oldValues Json? @map("old_values") newValues Json? @map("new_values") ipAddress String? @map("ip_address") userAgent String? @map("user_agent") createdAt DateTime @default(now()) @map("created_at") user User? @relation(fields: [userId], references: [id], onDelete: SetNull) @@map("audit_logs") } // ============================================================ // MODULO 3: PROYECTOS // ============================================================ model Project { id String @id @default(uuid()) code String @unique name String description String? type String category String client String? startDate DateTime @map("start_date") plannedEndDate DateTime @map("planned_end_date") actualEndDate DateTime? @map("actual_end_date") budget Decimal @db.Decimal(15, 2) contingencyPct Decimal @default(10) @map("contingency_pct") @db.Decimal(5, 2) currency String @default("USD") priority Priority @default(MEDIO) status ProjectStatus @default(ACTIVO) currentPhase String? @map("current_phase") methodology String? tags String[] ragStatus String @default("VERDE") @map("rag_status") progressPct Decimal @default(0) @map("progress_pct") @db.Decimal(5, 2) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") members ProjectMember[] tasks Task[] @@map("projects") } model ProjectMember { id String @id @default(uuid()) projectId String @map("project_id") userId String @map("user_id") role String joinedAt DateTime @default(now()) @map("joined_at") project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([projectId, userId]) @@map("project_members") } // ============================================================ // MODULO 4: TAREAS // ============================================================ model Task { id String @id @default(uuid()) projectId String @map("project_id") parentId String? @map("parent_id") wbsId String? @map("wbs_id") title String description String? assigneeId String? @map("assignee_id") createdById String @map("created_by_id") startDate DateTime? @map("start_date") dueDate DateTime? @map("due_date") estimatedHours Decimal? @map("estimated_hours") @db.Decimal(8, 2) actualHours Decimal? @map("actual_hours") @db.Decimal(8, 2) progressPct Decimal @default(0) @map("progress_pct") @db.Decimal(5, 2) status TaskStatus @default(PENDIENTE) priority Priority @default(MEDIO) estimatedCost Decimal? @map("estimated_cost") @db.Decimal(15, 2) actualCost Decimal? @map("actual_cost") @db.Decimal(15, 2) tags String[] createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) assignee User? @relation("TaskAssignee", fields: [assigneeId], references: [id]) creator User @relation("TaskCreator", fields: [createdById], references: [id]) parent Task? @relation("TaskChildren", fields: [parentId], references: [id]) children Task[] @relation("TaskChildren") comments Comment[] @@map("tasks") } model Comment { id String @id @default(uuid()) taskId String @map("task_id") userId String @map("user_id") content String createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") task Task @relation(fields: [taskId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id]) @@map("comments") }