Some checks failed
CI/CD Pipeline / Backend Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Tests (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
Complete rewrite from Express to NestJS with enterprise-grade features: ## Backend Improvements - Migrated from Express to NestJS 11.0.1 with TypeScript - Implemented Prisma ORM 7.3.0 for type-safe database access - Added CASL authorization system replacing role-based guards - Created global exception filters with structured logging - Implemented Auth0 JWT authentication with Passport.js - Added vehicle management with conflict detection - Enhanced event scheduling with driver/vehicle assignment - Comprehensive error handling and logging ## Frontend Improvements - Upgraded to React 19.2.0 with Vite 7.2.4 - Implemented CASL-based permission system - Added AbilityContext for declarative permissions - Created ErrorHandler utility for consistent error messages - Enhanced API client with request/response logging - Added War Room (Command Center) dashboard - Created VIP Schedule view with complete itineraries - Implemented Vehicle Management UI - Added mock data generators for testing (288 events across 20 VIPs) ## New Features - Vehicle fleet management (types, capacity, status tracking) - Complete 3-day Jamboree schedule generation - Individual VIP schedule pages with PDF export (planned) - Real-time War Room dashboard with auto-refresh - Permission-based navigation filtering - First user auto-approval as administrator ## Documentation - Created CASL_AUTHORIZATION.md (comprehensive guide) - Created ERROR_HANDLING.md (error handling patterns) - Updated CLAUDE.md with new architecture - Added migration guides and best practices ## Technical Debt Resolved - Removed custom authentication in favor of Auth0 - Replaced role checks with CASL abilities - Standardized error responses across API - Implemented proper TypeScript typing - Added comprehensive logging Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
228 lines
6.0 KiB
Plaintext
228 lines
6.0 KiB
Plaintext
// VIP Coordinator - Prisma Schema
|
|
// This is your database schema (source of truth)
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// ============================================
|
|
// User Management
|
|
// ============================================
|
|
|
|
model User {
|
|
id String @id @default(uuid())
|
|
auth0Id String @unique // Auth0 sub claim
|
|
email String @unique
|
|
name String?
|
|
picture String?
|
|
role Role @default(COORDINATOR)
|
|
isApproved Boolean @default(false)
|
|
driver Driver? // Optional linked driver account
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
deletedAt DateTime? // Soft delete
|
|
|
|
@@map("users")
|
|
}
|
|
|
|
enum Role {
|
|
ADMINISTRATOR
|
|
COORDINATOR
|
|
DRIVER
|
|
}
|
|
|
|
// ============================================
|
|
// VIP Management
|
|
// ============================================
|
|
|
|
model VIP {
|
|
id String @id @default(uuid())
|
|
name String
|
|
organization String?
|
|
department Department
|
|
arrivalMode ArrivalMode
|
|
expectedArrival DateTime? // For self-driving arrivals
|
|
airportPickup Boolean @default(false)
|
|
venueTransport Boolean @default(false)
|
|
notes String? @db.Text
|
|
flights Flight[]
|
|
events ScheduleEvent[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
deletedAt DateTime? // Soft delete
|
|
|
|
@@map("vips")
|
|
}
|
|
|
|
enum Department {
|
|
OFFICE_OF_DEVELOPMENT
|
|
ADMIN
|
|
}
|
|
|
|
enum ArrivalMode {
|
|
FLIGHT
|
|
SELF_DRIVING
|
|
}
|
|
|
|
// ============================================
|
|
// Flight Tracking
|
|
// ============================================
|
|
|
|
model Flight {
|
|
id String @id @default(uuid())
|
|
vipId String
|
|
vip VIP @relation(fields: [vipId], references: [id], onDelete: Cascade)
|
|
flightNumber String
|
|
flightDate DateTime
|
|
segment Int @default(1) // For multi-segment itineraries
|
|
departureAirport String // IATA code (e.g., "JFK")
|
|
arrivalAirport String // IATA code (e.g., "LAX")
|
|
scheduledDeparture DateTime?
|
|
scheduledArrival DateTime?
|
|
actualDeparture DateTime?
|
|
actualArrival DateTime?
|
|
status String? // scheduled, delayed, landed, etc.
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("flights")
|
|
@@index([vipId])
|
|
@@index([flightNumber, flightDate])
|
|
}
|
|
|
|
// ============================================
|
|
// Driver Management
|
|
// ============================================
|
|
|
|
model Driver {
|
|
id String @id @default(uuid())
|
|
name String
|
|
phone String
|
|
department Department?
|
|
userId String? @unique
|
|
user User? @relation(fields: [userId], references: [id])
|
|
|
|
// Shift/Availability
|
|
shiftStartTime DateTime? // When driver's shift starts
|
|
shiftEndTime DateTime? // When driver's shift ends
|
|
isAvailable Boolean @default(true)
|
|
|
|
events ScheduleEvent[]
|
|
assignedVehicle Vehicle? @relation("AssignedDriver")
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
deletedAt DateTime? // Soft delete
|
|
|
|
@@map("drivers")
|
|
}
|
|
|
|
// ============================================
|
|
// Vehicle Management
|
|
// ============================================
|
|
|
|
model Vehicle {
|
|
id String @id @default(uuid())
|
|
name String // "Blue Van", "Suburban #3"
|
|
type VehicleType @default(VAN)
|
|
licensePlate String?
|
|
seatCapacity Int // Total seats (e.g., 8)
|
|
status VehicleStatus @default(AVAILABLE)
|
|
|
|
// Current assignment
|
|
currentDriverId String? @unique
|
|
currentDriver Driver? @relation("AssignedDriver", fields: [currentDriverId], references: [id])
|
|
|
|
// Relationships
|
|
events ScheduleEvent[]
|
|
|
|
notes String? @db.Text
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
deletedAt DateTime? // Soft delete
|
|
|
|
@@map("vehicles")
|
|
}
|
|
|
|
enum VehicleType {
|
|
VAN // 7-15 seats
|
|
SUV // 5-8 seats
|
|
SEDAN // 4-5 seats
|
|
BUS // 15+ seats
|
|
GOLF_CART // 2-6 seats
|
|
TRUCK // For equipment/supplies
|
|
}
|
|
|
|
enum VehicleStatus {
|
|
AVAILABLE // Ready to use
|
|
IN_USE // Currently on a trip
|
|
MAINTENANCE // Out of service
|
|
RESERVED // Scheduled for upcoming trip
|
|
}
|
|
|
|
// ============================================
|
|
// Schedule & Event Management
|
|
// ============================================
|
|
|
|
model ScheduleEvent {
|
|
id String @id @default(uuid())
|
|
vipId String
|
|
vip VIP @relation(fields: [vipId], references: [id], onDelete: Cascade)
|
|
title String
|
|
|
|
// Location details
|
|
pickupLocation String?
|
|
dropoffLocation String?
|
|
location String? // For non-transport events
|
|
|
|
// Timing
|
|
startTime DateTime
|
|
endTime DateTime
|
|
actualStartTime DateTime?
|
|
actualEndTime DateTime?
|
|
|
|
description String? @db.Text
|
|
type EventType @default(TRANSPORT)
|
|
status EventStatus @default(SCHEDULED)
|
|
|
|
// Assignments
|
|
driverId String?
|
|
driver Driver? @relation(fields: [driverId], references: [id], onDelete: SetNull)
|
|
vehicleId String?
|
|
vehicle Vehicle? @relation(fields: [vehicleId], references: [id], onDelete: SetNull)
|
|
|
|
// Metadata
|
|
notes String? @db.Text
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
deletedAt DateTime? // Soft delete
|
|
|
|
@@map("schedule_events")
|
|
@@index([vipId])
|
|
@@index([driverId])
|
|
@@index([vehicleId])
|
|
@@index([startTime, endTime])
|
|
@@index([status])
|
|
}
|
|
|
|
enum EventType {
|
|
TRANSPORT
|
|
MEETING
|
|
EVENT
|
|
MEAL
|
|
ACCOMMODATION
|
|
}
|
|
|
|
enum EventStatus {
|
|
SCHEDULED
|
|
IN_PROGRESS
|
|
COMPLETED
|
|
CANCELLED
|
|
}
|