// Moraworld Imports — Schema v0 (Fase 0–1) // Multi-tenant por tenant_id en todas las tablas de negocio generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ─── Enums ─────────────────────────────────────────────────── enum UserRole { SUPER_ADMIN ADMIN_EMPRESA OPERADOR_BODEGA AGENTE_ADUANERO CLIENTE SOPORTE } enum PackageStatus { REGISTRADO EN_TRANSITO_BODEGA RECIBIDO_BODEGA EN_VERIFICACION VERIFICADO DECLARACION_ADUANERA EN_TRANSITO_ECUADOR EN_ADUANA_ECUADOR LISTO_ENTREGA ENTREGADO INCIDENCIA } enum PreAlertStatus { PENDIENTE VINCULADA CANCELADA } // ─── Tenant (multi-tenant) ─────────────────────────────────── model Tenant { id String @id @default(cuid()) slug String @unique name String isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt users User[] suites Suite[] packages Package[] preAlerts PreAlert[] } // ─── Usuarios ──────────────────────────────────────────────── model User { id String @id @default(cuid()) tenantId String email String passwordHash String firstName String lastName String phone String? role UserRole @default(CLIENTE) mfaEnabled Boolean @default(false) mfaSecret String? isActive Boolean @default(true) lastLoginAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) suite Suite? packages Package[] @@unique([tenantId, email]) @@index([tenantId]) } // ─── Casillero / Suite ─────────────────────────────────────── model Suite { id String @id @default(cuid()) tenantId String userId String @unique code String // ej: EC-00345 createdAt DateTime @default(now()) tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([tenantId, code]) @@index([tenantId]) } // ─── Paquetes ──────────────────────────────────────────────── model Package { id String @id @default(cuid()) tenantId String userId String trackingId String @unique // EC-YYYYMMDD-XXXXXX status PackageStatus @default(REGISTRADO) description String store String? declaredValue Decimal @db.Decimal(10, 2) declaredWeight Decimal? @db.Decimal(8, 2) actualWeight Decimal? @db.Decimal(8, 2) vendorTracking String? productUrl String? paidAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) statusHistory PackageStatusHistory[] preAlert PreAlert? @@index([tenantId, status]) @@index([userId]) } model PackageStatusHistory { id String @id @default(cuid()) packageId String status PackageStatus note String? createdBy String? createdAt DateTime @default(now()) package Package @relation(fields: [packageId], references: [id], onDelete: Cascade) @@index([packageId]) } // ─── Pre-alertas ───────────────────────────────────────────── model PreAlert { id String @id @default(cuid()) tenantId String packageId String? @unique store String vendorTracking String? description String declaredValue Decimal @db.Decimal(10, 2) invoiceKey String? status PreAlertStatus @default(PENDIENTE) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade) package Package? @relation(fields: [packageId], references: [id]) @@index([tenantId]) } // ─── Auditoría (append-only) ─────────────────────────────── model AuditLog { id String @id @default(cuid()) tenantId String? userId String? action String resource String? resourceId String? metadata Json? ipAddress String? createdAt DateTime @default(now()) @@index([tenantId, createdAt]) @@index([userId]) }