feat: update seed data with BSA Jamboree scenario
Replaces generic test data with a realistic BSA Jamboree scenario that demonstrates party sizes, shared itinerary items, and linked transport legs. Includes 6 VIPs with varying party sizes, 7 shared events, 15 transport legs, 6 vehicles, and 4 drivers. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,145 +3,153 @@ import { PrismaClient, Role, Department, ArrivalMode, EventType, EventStatus, Ve
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
console.log('🌱 Seeding database...');
|
||||
console.log('🌱 Seeding database with BSA Jamboree scenario...');
|
||||
|
||||
// Clean up existing data (careful in production!)
|
||||
// Clean up existing data (preserves users/auth accounts)
|
||||
await prisma.scheduleEvent.deleteMany({});
|
||||
await prisma.flight.deleteMany({});
|
||||
await prisma.vehicle.deleteMany({});
|
||||
await prisma.driver.deleteMany({});
|
||||
// Don't delete drivers linked to users — only standalone test drivers
|
||||
await prisma.driver.deleteMany({ where: { userId: null } });
|
||||
await prisma.vIP.deleteMany({});
|
||||
await prisma.user.deleteMany({});
|
||||
|
||||
console.log('✅ Cleared existing data');
|
||||
console.log('✅ Cleared existing test data (preserved user accounts)');
|
||||
|
||||
// Create sample users
|
||||
const admin = await prisma.user.create({
|
||||
// =============================================
|
||||
// VEHICLES — BSA Jamboree fleet
|
||||
// =============================================
|
||||
|
||||
const suburban1 = await prisma.vehicle.create({
|
||||
data: {
|
||||
auth0Id: 'auth0|admin-sample-id',
|
||||
email: 'admin@example.com',
|
||||
name: 'Admin User',
|
||||
role: Role.ADMINISTRATOR,
|
||||
isApproved: true,
|
||||
},
|
||||
});
|
||||
|
||||
const coordinator = await prisma.user.create({
|
||||
data: {
|
||||
auth0Id: 'auth0|coordinator-sample-id',
|
||||
email: 'coordinator@example.com',
|
||||
name: 'Coordinator User',
|
||||
role: Role.COORDINATOR,
|
||||
isApproved: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Note: test@test.com user is auto-created and auto-approved on first login (see auth.service.ts)
|
||||
|
||||
console.log('✅ Created sample users');
|
||||
|
||||
// Create sample vehicles with capacity
|
||||
const blackSUV = await prisma.vehicle.create({
|
||||
data: {
|
||||
name: 'Black Suburban',
|
||||
name: 'Black Suburban #1',
|
||||
type: VehicleType.SUV,
|
||||
licensePlate: 'ABC-1234',
|
||||
licensePlate: 'BSA-001',
|
||||
seatCapacity: 6,
|
||||
status: VehicleStatus.AVAILABLE,
|
||||
notes: 'Leather interior, tinted windows',
|
||||
notes: 'Primary VIP vehicle, leather interior',
|
||||
},
|
||||
});
|
||||
|
||||
const suburban2 = await prisma.vehicle.create({
|
||||
data: {
|
||||
name: 'Black Suburban #2',
|
||||
type: VehicleType.SUV,
|
||||
licensePlate: 'BSA-002',
|
||||
seatCapacity: 6,
|
||||
status: VehicleStatus.AVAILABLE,
|
||||
notes: 'Secondary VIP vehicle',
|
||||
},
|
||||
});
|
||||
|
||||
const whiteVan = await prisma.vehicle.create({
|
||||
data: {
|
||||
name: 'White Sprinter Van',
|
||||
name: 'White 15-Passenger Van',
|
||||
type: VehicleType.VAN,
|
||||
licensePlate: 'XYZ-5678',
|
||||
seatCapacity: 12,
|
||||
licensePlate: 'BSA-003',
|
||||
seatCapacity: 14,
|
||||
status: VehicleStatus.AVAILABLE,
|
||||
notes: 'High roof, wheelchair accessible',
|
||||
notes: 'Large group transport',
|
||||
},
|
||||
});
|
||||
|
||||
const blueSedan = await prisma.vehicle.create({
|
||||
const golfCart1 = await prisma.vehicle.create({
|
||||
data: {
|
||||
name: 'Blue Camry',
|
||||
type: VehicleType.SEDAN,
|
||||
licensePlate: 'DEF-9012',
|
||||
name: 'Golf Cart A',
|
||||
type: VehicleType.GOLF_CART,
|
||||
licensePlate: 'GC-A',
|
||||
seatCapacity: 4,
|
||||
status: VehicleStatus.AVAILABLE,
|
||||
notes: 'Fuel efficient, good for short trips',
|
||||
notes: 'On-site shuttle between venues',
|
||||
},
|
||||
});
|
||||
|
||||
const grayBus = await prisma.vehicle.create({
|
||||
const golfCart2 = await prisma.vehicle.create({
|
||||
data: {
|
||||
name: 'Gray Charter Bus',
|
||||
type: VehicleType.BUS,
|
||||
licensePlate: 'BUS-0001',
|
||||
seatCapacity: 40,
|
||||
name: 'Golf Cart B',
|
||||
type: VehicleType.GOLF_CART,
|
||||
licensePlate: 'GC-B',
|
||||
seatCapacity: 4,
|
||||
status: VehicleStatus.AVAILABLE,
|
||||
notes: 'Full size charter bus, A/C, luggage compartment',
|
||||
notes: 'On-site shuttle between venues',
|
||||
},
|
||||
});
|
||||
|
||||
console.log('✅ Created sample vehicles with capacities');
|
||||
|
||||
// Create sample drivers
|
||||
const driver1 = await prisma.driver.create({
|
||||
const charterBus = await prisma.vehicle.create({
|
||||
data: {
|
||||
name: 'John Smith',
|
||||
phone: '+1 (555) 123-4567',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
name: 'Charter Bus',
|
||||
type: VehicleType.BUS,
|
||||
licensePlate: 'BSA-BUS',
|
||||
seatCapacity: 45,
|
||||
status: VehicleStatus.AVAILABLE,
|
||||
notes: 'Full-size charter for large group moves',
|
||||
},
|
||||
});
|
||||
|
||||
const driver2 = await prisma.driver.create({
|
||||
console.log('✅ Created 6 vehicles');
|
||||
|
||||
// =============================================
|
||||
// DRIVERS
|
||||
// =============================================
|
||||
|
||||
const driverTom = await prisma.driver.create({
|
||||
data: {
|
||||
name: 'Jane Doe',
|
||||
phone: '+1 (555) 987-6543',
|
||||
name: 'Tom Bradley',
|
||||
phone: '+1 (555) 100-0001',
|
||||
department: Department.ADMIN,
|
||||
},
|
||||
});
|
||||
|
||||
const driver3 = await prisma.driver.create({
|
||||
const driverMaria = await prisma.driver.create({
|
||||
data: {
|
||||
name: 'Amanda Washington',
|
||||
phone: '+1 (555) 234-5678',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
},
|
||||
});
|
||||
|
||||
const driver4 = await prisma.driver.create({
|
||||
data: {
|
||||
name: 'Michael Thompson',
|
||||
phone: '+1 (555) 876-5432',
|
||||
name: 'Maria Gonzalez',
|
||||
phone: '+1 (555) 100-0002',
|
||||
department: Department.ADMIN,
|
||||
},
|
||||
});
|
||||
|
||||
console.log('✅ Created sample drivers');
|
||||
|
||||
// Create sample VIPs
|
||||
const vip1 = await prisma.vIP.create({
|
||||
const driverKevin = await prisma.driver.create({
|
||||
data: {
|
||||
name: 'Dr. Robert Johnson',
|
||||
organization: 'Tech Corporation',
|
||||
name: 'Kevin Park',
|
||||
phone: '+1 (555) 100-0003',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
},
|
||||
});
|
||||
|
||||
const driverLisa = await prisma.driver.create({
|
||||
data: {
|
||||
name: 'Lisa Chen',
|
||||
phone: '+1 (555) 100-0004',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
},
|
||||
});
|
||||
|
||||
console.log('✅ Created 4 drivers');
|
||||
|
||||
// =============================================
|
||||
// VIPs — BSA Jamboree dignitaries WITH PARTY SIZES
|
||||
// =============================================
|
||||
|
||||
// Chief Scout Executive — travels with 2 handlers
|
||||
const vipRoger = await prisma.vIP.create({
|
||||
data: {
|
||||
name: 'Roger Mosby',
|
||||
organization: 'Boy Scouts of America',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
arrivalMode: ArrivalMode.FLIGHT,
|
||||
airportPickup: true,
|
||||
venueTransport: true,
|
||||
notes: 'Prefers window seat, dietary restriction: vegetarian',
|
||||
partySize: 3, // Roger + 2 handlers
|
||||
notes: 'Chief Scout Executive. Travels with 2 staff handlers. Requires accessible vehicle.',
|
||||
flights: {
|
||||
create: [
|
||||
{
|
||||
flightNumber: 'AA123',
|
||||
flightDate: new Date('2026-02-15'),
|
||||
flightNumber: 'UA1142',
|
||||
flightDate: new Date('2026-02-05'),
|
||||
segment: 1,
|
||||
departureAirport: 'JFK',
|
||||
arrivalAirport: 'LAX',
|
||||
scheduledDeparture: new Date('2026-02-15T08:00:00'),
|
||||
scheduledArrival: new Date('2026-02-15T11:30:00'),
|
||||
departureAirport: 'IAD',
|
||||
arrivalAirport: 'DEN',
|
||||
scheduledDeparture: new Date('2026-02-05T07:00:00'),
|
||||
scheduledArrival: new Date('2026-02-05T09:15:00'),
|
||||
status: 'scheduled',
|
||||
},
|
||||
],
|
||||
@@ -149,199 +157,516 @@ async function main() {
|
||||
},
|
||||
});
|
||||
|
||||
const vip2 = await prisma.vIP.create({
|
||||
// National Board Chair — travels with spouse
|
||||
const vipPatricia = await prisma.vIP.create({
|
||||
data: {
|
||||
name: 'Ms. Sarah Williams',
|
||||
organization: 'Global Foundation',
|
||||
name: 'Patricia Hawkins',
|
||||
organization: 'BSA National Board',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
arrivalMode: ArrivalMode.FLIGHT,
|
||||
airportPickup: true,
|
||||
venueTransport: true,
|
||||
partySize: 2, // Patricia + spouse
|
||||
notes: 'National Board Chair. Traveling with husband (Richard). Both attend all events.',
|
||||
flights: {
|
||||
create: [
|
||||
{
|
||||
flightNumber: 'DL783',
|
||||
flightDate: new Date('2026-02-05'),
|
||||
segment: 1,
|
||||
departureAirport: 'ATL',
|
||||
arrivalAirport: 'DEN',
|
||||
scheduledDeparture: new Date('2026-02-05T06:30:00'),
|
||||
scheduledArrival: new Date('2026-02-05T08:45:00'),
|
||||
status: 'scheduled',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Major Donor — solo
|
||||
const vipJames = await prisma.vIP.create({
|
||||
data: {
|
||||
name: 'James Whitfield III',
|
||||
organization: 'Whitfield Foundation',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
arrivalMode: ArrivalMode.FLIGHT,
|
||||
airportPickup: true,
|
||||
venueTransport: true,
|
||||
partySize: 1, // Solo
|
||||
notes: 'Major donor ($2M+). Eagle Scout class of 1978. Very punctual — do not be late.',
|
||||
flights: {
|
||||
create: [
|
||||
{
|
||||
flightNumber: 'AA456',
|
||||
flightDate: new Date('2026-02-05'),
|
||||
segment: 1,
|
||||
departureAirport: 'DFW',
|
||||
arrivalAirport: 'DEN',
|
||||
scheduledDeparture: new Date('2026-02-05T10:00:00'),
|
||||
scheduledArrival: new Date('2026-02-05T11:30:00'),
|
||||
status: 'scheduled',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Keynote Speaker — travels with assistant
|
||||
const vipDrBaker = await prisma.vIP.create({
|
||||
data: {
|
||||
name: 'Dr. Angela Baker',
|
||||
organization: 'National Geographic Society',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
arrivalMode: ArrivalMode.FLIGHT,
|
||||
airportPickup: true,
|
||||
venueTransport: true,
|
||||
partySize: 2, // Dr. Baker + assistant
|
||||
notes: 'Keynote speaker, Day 1. Traveling with assistant (Marcus). Needs quiet space before keynote.',
|
||||
flights: {
|
||||
create: [
|
||||
{
|
||||
flightNumber: 'SW221',
|
||||
flightDate: new Date('2026-02-05'),
|
||||
segment: 1,
|
||||
departureAirport: 'BWI',
|
||||
arrivalAirport: 'DEN',
|
||||
scheduledDeparture: new Date('2026-02-05T08:15:00'),
|
||||
scheduledArrival: new Date('2026-02-05T10:40:00'),
|
||||
status: 'scheduled',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Governor — travels with 3 (security detail + aide)
|
||||
const vipGovMartinez = await prisma.vIP.create({
|
||||
data: {
|
||||
name: 'Gov. Carlos Martinez',
|
||||
organization: 'State of Colorado',
|
||||
department: Department.ADMIN,
|
||||
arrivalMode: ArrivalMode.SELF_DRIVING,
|
||||
expectedArrival: new Date('2026-02-16T14:00:00'),
|
||||
expectedArrival: new Date('2026-02-05T13:00:00'),
|
||||
airportPickup: false,
|
||||
venueTransport: true,
|
||||
notes: 'Bringing assistant',
|
||||
partySize: 4, // Governor + security officer + aide + driver (their own driver stays)
|
||||
notes: 'Governor arriving by motorcade. Party of 4: Gov, 1 state trooper, 1 aide, 1 advance staff. Their driver does NOT need a seat.',
|
||||
},
|
||||
});
|
||||
|
||||
const vip3 = await prisma.vIP.create({
|
||||
// Local Council President — solo, self-driving
|
||||
const vipSusan = await prisma.vIP.create({
|
||||
data: {
|
||||
name: 'Emily Richardson (Harvard University)',
|
||||
organization: 'Harvard University',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
arrivalMode: ArrivalMode.FLIGHT,
|
||||
airportPickup: true,
|
||||
name: 'Susan O\'Malley',
|
||||
organization: 'Denver Area Council BSA',
|
||||
department: Department.ADMIN,
|
||||
arrivalMode: ArrivalMode.SELF_DRIVING,
|
||||
expectedArrival: new Date('2026-02-05T08:00:00'),
|
||||
airportPickup: false,
|
||||
venueTransport: true,
|
||||
notes: 'Board member, requires accessible vehicle',
|
||||
partySize: 1,
|
||||
notes: 'Local council president. Knows the venue well. Can help with directions if needed.',
|
||||
},
|
||||
});
|
||||
|
||||
const vip4 = await prisma.vIP.create({
|
||||
console.log('✅ Created 6 VIPs with party sizes');
|
||||
console.log(' Roger Mosby (party: 3), Patricia Hawkins (party: 2)');
|
||||
console.log(' James Whitfield III (party: 1), Dr. Angela Baker (party: 2)');
|
||||
console.log(' Gov. Martinez (party: 4), Susan O\'Malley (party: 1)');
|
||||
|
||||
// =============================================
|
||||
// SHARED ITINERARY ITEMS (master events)
|
||||
// These are the actual activities everyone attends
|
||||
// =============================================
|
||||
|
||||
// Use dates relative to "today + 2 days" so they show up in the War Room
|
||||
const jamboreeDay1 = new Date();
|
||||
jamboreeDay1.setDate(jamboreeDay1.getDate() + 2);
|
||||
jamboreeDay1.setHours(0, 0, 0, 0);
|
||||
|
||||
const jamboreeDay2 = new Date(jamboreeDay1);
|
||||
jamboreeDay2.setDate(jamboreeDay2.getDate() + 1);
|
||||
|
||||
// Day 1 shared events
|
||||
const openingCeremony = await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
name: 'David Chen (Stanford)',
|
||||
organization: 'Stanford University',
|
||||
department: Department.OFFICE_OF_DEVELOPMENT,
|
||||
arrivalMode: ArrivalMode.FLIGHT,
|
||||
airportPickup: true,
|
||||
venueTransport: true,
|
||||
notes: 'Keynote speaker',
|
||||
},
|
||||
});
|
||||
|
||||
console.log('✅ Created sample VIPs');
|
||||
|
||||
// Create sample schedule events (unified activities) - NOW WITH MULTIPLE VIPS!
|
||||
|
||||
// Multi-VIP rideshare to Campfire Night (3 VIPs in one SUV)
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vip3.id, vip4.id, vip1.id], // 3 VIPs sharing a ride
|
||||
title: 'Transport to Campfire Night',
|
||||
pickupLocation: 'Grand Hotel Lobby',
|
||||
dropoffLocation: 'Camp Amphitheater',
|
||||
startTime: new Date('2026-02-15T19:45:00'),
|
||||
endTime: new Date('2026-02-15T20:00:00'),
|
||||
description: 'Rideshare: Emily, David, and Dr. Johnson to campfire',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driver3.id,
|
||||
vehicleId: blackSUV.id, // 3 VIPs in 6-seat SUV (3/6 seats used)
|
||||
},
|
||||
});
|
||||
|
||||
// Single VIP transport
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vip1.id],
|
||||
title: 'Airport Pickup - Dr. Johnson',
|
||||
pickupLocation: 'LAX Terminal 4',
|
||||
dropoffLocation: 'Grand Hotel',
|
||||
startTime: new Date('2026-02-15T11:30:00'),
|
||||
endTime: new Date('2026-02-15T12:30:00'),
|
||||
description: 'Pick up Dr. Johnson from LAX',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driver1.id,
|
||||
vehicleId: blueSedan.id, // 1 VIP in 4-seat sedan (1/4 seats used)
|
||||
},
|
||||
});
|
||||
|
||||
// Two VIPs sharing lunch transport
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vip1.id, vip2.id],
|
||||
title: 'Transport to Lunch - Day 1',
|
||||
pickupLocation: 'Grand Hotel Lobby',
|
||||
dropoffLocation: 'Main Dining Hall',
|
||||
startTime: new Date('2026-02-15T11:45:00'),
|
||||
endTime: new Date('2026-02-15T12:00:00'),
|
||||
description: 'Rideshare: Dr. Johnson and Ms. Williams to lunch',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driver2.id,
|
||||
vehicleId: blueSedan.id, // 2 VIPs in 4-seat sedan (2/4 seats used)
|
||||
},
|
||||
});
|
||||
|
||||
// Large group transport in van
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vip1.id, vip2.id, vip3.id, vip4.id],
|
||||
title: 'Morning Shuttle to Conference',
|
||||
pickupLocation: 'Grand Hotel Lobby',
|
||||
dropoffLocation: 'Conference Center',
|
||||
startTime: new Date('2026-02-15T08:00:00'),
|
||||
endTime: new Date('2026-02-15T08:30:00'),
|
||||
description: 'All VIPs to morning conference session',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driver4.id,
|
||||
vehicleId: whiteVan.id, // 4 VIPs in 12-seat van (4/12 seats used)
|
||||
},
|
||||
});
|
||||
|
||||
// Non-transport activities (unified system)
|
||||
|
||||
// Opening Ceremony - all VIPs attending
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vip1.id, vip2.id, vip3.id, vip4.id],
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipGovMartinez.id, vipSusan.id],
|
||||
title: 'Opening Ceremony',
|
||||
location: 'Main Stage',
|
||||
startTime: new Date('2026-02-15T10:00:00'),
|
||||
endTime: new Date('2026-02-15T11:30:00'),
|
||||
description: 'Welcome and opening remarks',
|
||||
location: 'Main Arena',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 10 * 60 * 60 * 1000), // 10:00 AM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM
|
||||
description: 'National anthem, color guard, welcome remarks by Chief Scout Executive. All VIPs seated in reserved section.',
|
||||
type: EventType.EVENT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
},
|
||||
});
|
||||
|
||||
// Lunch - Day 1 (all VIPs)
|
||||
await prisma.scheduleEvent.create({
|
||||
const vipLuncheon = await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vip1.id, vip2.id, vip3.id, vip4.id],
|
||||
title: 'Lunch - Day 1',
|
||||
location: 'Main Dining Hall',
|
||||
startTime: new Date('2026-02-15T12:00:00'),
|
||||
endTime: new Date('2026-02-15T13:30:00'),
|
||||
description: 'Day 1 lunch for all attendees',
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipGovMartinez.id, vipSusan.id],
|
||||
title: 'VIP Luncheon',
|
||||
location: 'Eagle Lodge Private Dining',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 12 * 60 * 60 * 1000), // 12:00 PM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 13.5 * 60 * 60 * 1000), // 1:30 PM
|
||||
description: 'Private luncheon for VIP guests and BSA leadership. Seated service.',
|
||||
type: EventType.MEAL,
|
||||
status: EventStatus.SCHEDULED,
|
||||
},
|
||||
});
|
||||
|
||||
// Campfire Night (all VIPs)
|
||||
await prisma.scheduleEvent.create({
|
||||
const keynoteAddress = await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vip1.id, vip2.id, vip3.id, vip4.id],
|
||||
title: 'Campfire Night',
|
||||
location: 'Camp Amphitheater',
|
||||
startTime: new Date('2026-02-15T20:00:00'),
|
||||
endTime: new Date('2026-02-15T22:00:00'),
|
||||
description: 'Evening campfire and networking',
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id],
|
||||
title: 'Keynote Address — Dr. Baker',
|
||||
location: 'Main Arena',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 14 * 60 * 60 * 1000), // 2:00 PM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 15.5 * 60 * 60 * 1000), // 3:30 PM
|
||||
description: 'Dr. Angela Baker delivers keynote on "Adventure and Discovery." VIPs in reserved front section.',
|
||||
type: EventType.EVENT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
notes: 'Gov. Martinez departs before keynote — not attending this one.',
|
||||
},
|
||||
});
|
||||
|
||||
// Private meeting - just Dr. Johnson and Ms. Williams
|
||||
await prisma.scheduleEvent.create({
|
||||
const donorMeeting = await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vip1.id, vip2.id],
|
||||
title: 'Donor Meeting',
|
||||
location: 'Conference Room A',
|
||||
startTime: new Date('2026-02-15T14:00:00'),
|
||||
endTime: new Date('2026-02-15T15:00:00'),
|
||||
description: 'Private meeting with development team',
|
||||
vipIds: [vipJames.id, vipPatricia.id, vipRoger.id],
|
||||
title: 'Donor Strategy Meeting',
|
||||
location: 'Eagle Lodge Conference Room',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 16 * 60 * 60 * 1000), // 4:00 PM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 17 * 60 * 60 * 1000), // 5:00 PM
|
||||
description: 'Private meeting: Whitfield Foundation partnership discussion with BSA leadership.',
|
||||
type: EventType.MEETING,
|
||||
status: EventStatus.SCHEDULED,
|
||||
},
|
||||
});
|
||||
|
||||
console.log('✅ Created sample schedule events with multi-VIP rideshares and activities');
|
||||
const campfireNight = await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id],
|
||||
title: 'Campfire Night',
|
||||
location: 'Campfire Bowl',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 20 * 60 * 60 * 1000), // 8:00 PM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 22 * 60 * 60 * 1000), // 10:00 PM
|
||||
description: 'Traditional Jamboree campfire with skits, songs, and awards. VIP seating near stage.',
|
||||
type: EventType.EVENT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
},
|
||||
});
|
||||
|
||||
console.log('\n🎉 Database seeded successfully!');
|
||||
console.log('\nSample Users:');
|
||||
console.log('- Admin: admin@example.com');
|
||||
console.log('- Coordinator: coordinator@example.com');
|
||||
console.log('\nSample VIPs:');
|
||||
console.log('- Dr. Robert Johnson (Flight arrival)');
|
||||
console.log('- Ms. Sarah Williams (Self-driving)');
|
||||
console.log('- Emily Richardson (Harvard University)');
|
||||
console.log('- David Chen (Stanford)');
|
||||
console.log('\nSample Drivers:');
|
||||
console.log('- John Smith');
|
||||
console.log('- Jane Doe');
|
||||
console.log('- Amanda Washington');
|
||||
console.log('- Michael Thompson');
|
||||
console.log('\nSample Vehicles:');
|
||||
console.log('- Black Suburban (SUV, 6 seats)');
|
||||
console.log('- White Sprinter Van (Van, 12 seats)');
|
||||
console.log('- Blue Camry (Sedan, 4 seats)');
|
||||
console.log('- Gray Charter Bus (Bus, 40 seats)');
|
||||
console.log('\nSchedule Tasks (Multi-VIP Examples):');
|
||||
console.log('- 3 VIPs sharing SUV to Campfire (3/6 seats)');
|
||||
console.log('- 2 VIPs sharing sedan to Lunch (2/4 seats)');
|
||||
console.log('- 4 VIPs in van to Conference (4/12 seats)');
|
||||
console.log('- 1 VIP solo in sedan from Airport (1/4 seats)');
|
||||
// Day 2 shared events
|
||||
const eagleScoutCeremony = await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipSusan.id],
|
||||
title: 'Eagle Scout Recognition Ceremony',
|
||||
location: 'Main Arena',
|
||||
startTime: new Date(jamboreeDay2.getTime() + 9 * 60 * 60 * 1000), // 9:00 AM
|
||||
endTime: new Date(jamboreeDay2.getTime() + 11 * 60 * 60 * 1000), // 11:00 AM
|
||||
description: 'Honoring 200+ new Eagle Scouts. James Whitfield giving remarks as Eagle Scout alumnus.',
|
||||
type: EventType.EVENT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
},
|
||||
});
|
||||
|
||||
const farewellBrunch = await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id],
|
||||
title: 'Farewell Brunch',
|
||||
location: 'Eagle Lodge Private Dining',
|
||||
startTime: new Date(jamboreeDay2.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM
|
||||
endTime: new Date(jamboreeDay2.getTime() + 13 * 60 * 60 * 1000), // 1:00 PM
|
||||
description: 'Final meal together before departures. Thank-you gifts distributed.',
|
||||
type: EventType.MEAL,
|
||||
status: EventStatus.SCHEDULED,
|
||||
},
|
||||
});
|
||||
|
||||
console.log('✅ Created 7 shared itinerary items (master events)');
|
||||
|
||||
// =============================================
|
||||
// TRANSPORT LEGS — linked to master events
|
||||
// These are the rides TO and FROM the shared events
|
||||
// =============================================
|
||||
|
||||
// --- AIRPORT PICKUPS (Day 1 morning) ---
|
||||
|
||||
// Roger Mosby (party of 3) — airport pickup
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id],
|
||||
title: 'Airport Pickup — Roger Mosby',
|
||||
pickupLocation: 'DEN Terminal West, Door 507',
|
||||
dropoffLocation: 'Jamboree Camp — VIP Lodge',
|
||||
startTime: new Date('2026-02-05T09:15:00'),
|
||||
endTime: new Date('2026-02-05T10:00:00'),
|
||||
description: 'Party of 3 (Roger + 2 handlers). UA1142 lands 9:15 AM.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverTom.id,
|
||||
vehicleId: suburban1.id, // 3 people in 6-seat SUV
|
||||
},
|
||||
});
|
||||
|
||||
// Patricia Hawkins (party of 2) — airport pickup
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipPatricia.id],
|
||||
title: 'Airport Pickup — Patricia Hawkins',
|
||||
pickupLocation: 'DEN Terminal South, Door 610',
|
||||
dropoffLocation: 'Jamboree Camp — VIP Lodge',
|
||||
startTime: new Date('2026-02-05T08:45:00'),
|
||||
endTime: new Date('2026-02-05T09:30:00'),
|
||||
description: 'Party of 2 (Patricia + husband Richard). DL783 lands 8:45 AM.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverMaria.id,
|
||||
vehicleId: suburban2.id, // 2 people in 6-seat SUV
|
||||
},
|
||||
});
|
||||
|
||||
// Dr. Baker (party of 2) + James Whitfield (party of 1) — shared airport pickup
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipDrBaker.id, vipJames.id],
|
||||
title: 'Airport Pickup — Dr. Baker & Whitfield',
|
||||
pickupLocation: 'DEN Terminal East, Arrivals Curb',
|
||||
dropoffLocation: 'Jamboree Camp — VIP Lodge',
|
||||
startTime: new Date('2026-02-05T11:30:00'),
|
||||
endTime: new Date('2026-02-05T12:15:00'),
|
||||
description: 'Shared pickup. Dr. Baker (party 2: + assistant Marcus) lands 10:40 AM. Whitfield (solo) lands 11:30 AM. Wait for both.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverKevin.id,
|
||||
vehicleId: suburban1.id, // 3 people total in 6-seat SUV
|
||||
notes: 'Whitfield lands later — coordinate timing. Baker party can wait in VIP lounge.',
|
||||
},
|
||||
});
|
||||
|
||||
// --- DAY 1: TRANSPORT TO OPENING CEREMONY ---
|
||||
|
||||
// Group shuttle: all VIPs to Opening Ceremony (linked to master event)
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id],
|
||||
title: 'Transport to Opening Ceremony',
|
||||
pickupLocation: 'VIP Lodge',
|
||||
dropoffLocation: 'Main Arena — VIP Entrance',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 9.5 * 60 * 60 * 1000), // 9:30 AM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 9.75 * 60 * 60 * 1000), // 9:45 AM
|
||||
description: 'All VIPs to Opening Ceremony. Total party: 9 people (5 VIPs + entourage).',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverTom.id,
|
||||
vehicleId: whiteVan.id, // 9 people in 14-seat van
|
||||
masterEventId: openingCeremony.id,
|
||||
notes: 'Gov. Martinez arriving separately by motorcade.',
|
||||
},
|
||||
});
|
||||
|
||||
// --- DAY 1: TRANSPORT TO VIP LUNCHEON ---
|
||||
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipGovMartinez.id, vipSusan.id],
|
||||
title: 'Transport to VIP Luncheon',
|
||||
pickupLocation: 'Main Arena — VIP Entrance',
|
||||
dropoffLocation: 'Eagle Lodge',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 11.75 * 60 * 60 * 1000), // 11:45 AM
|
||||
description: 'All VIPs + entourage to lunch. Total: 13 people.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverTom.id,
|
||||
vehicleId: whiteVan.id, // 13 people in 14-seat van — tight!
|
||||
masterEventId: vipLuncheon.id,
|
||||
},
|
||||
});
|
||||
|
||||
// --- DAY 1: TRANSPORT TO KEYNOTE ---
|
||||
|
||||
// Two vehicles needed — Gov. Martinez departed, but still 9 people
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id],
|
||||
title: 'Transport to Keynote (Group A)',
|
||||
pickupLocation: 'Eagle Lodge',
|
||||
dropoffLocation: 'Main Arena — VIP Entrance',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 13.75 * 60 * 60 * 1000), // 1:45 PM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 14 * 60 * 60 * 1000), // 2:00 PM
|
||||
description: 'Group A: Roger (3), Patricia (2), James (1) = 6 people',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverMaria.id,
|
||||
vehicleId: suburban1.id, // 6 people in 6-seat SUV — exactly full
|
||||
masterEventId: keynoteAddress.id,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipDrBaker.id, vipSusan.id],
|
||||
title: 'Transport to Keynote (Group B)',
|
||||
pickupLocation: 'Eagle Lodge',
|
||||
dropoffLocation: 'Main Arena — Backstage',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 13.5 * 60 * 60 * 1000), // 1:30 PM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 13.75 * 60 * 60 * 1000), // 1:45 PM
|
||||
description: 'Group B: Dr. Baker (2) + Susan (1) = 3 people. Baker goes backstage early for prep.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverLisa.id,
|
||||
vehicleId: golfCart1.id, // 3 people in 4-seat golf cart
|
||||
masterEventId: keynoteAddress.id,
|
||||
},
|
||||
});
|
||||
|
||||
// --- DAY 1: TRANSPORT TO DONOR MEETING ---
|
||||
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipJames.id, vipPatricia.id, vipRoger.id],
|
||||
title: 'Transport to Donor Meeting',
|
||||
pickupLocation: 'Main Arena — VIP Entrance',
|
||||
dropoffLocation: 'Eagle Lodge Conference Room',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 15.75 * 60 * 60 * 1000), // 3:45 PM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 16 * 60 * 60 * 1000), // 4:00 PM
|
||||
description: 'Roger (3) + Patricia (2) + James (1) = 6 people to donor meeting',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverKevin.id,
|
||||
vehicleId: suburban2.id,
|
||||
masterEventId: donorMeeting.id,
|
||||
},
|
||||
});
|
||||
|
||||
// --- DAY 1: TRANSPORT TO CAMPFIRE ---
|
||||
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id],
|
||||
title: 'Transport to Campfire Night',
|
||||
pickupLocation: 'VIP Lodge',
|
||||
dropoffLocation: 'Campfire Bowl — VIP Section',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 19.5 * 60 * 60 * 1000), // 7:30 PM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 19.75 * 60 * 60 * 1000), // 7:45 PM
|
||||
description: 'All VIPs to campfire. 9 people total.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverTom.id,
|
||||
vehicleId: whiteVan.id,
|
||||
masterEventId: campfireNight.id,
|
||||
},
|
||||
});
|
||||
|
||||
// Return from campfire
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id],
|
||||
title: 'Return from Campfire Night',
|
||||
pickupLocation: 'Campfire Bowl — VIP Section',
|
||||
dropoffLocation: 'VIP Lodge',
|
||||
startTime: new Date(jamboreeDay1.getTime() + 22 * 60 * 60 * 1000), // 10:00 PM
|
||||
endTime: new Date(jamboreeDay1.getTime() + 22.25 * 60 * 60 * 1000), // 10:15 PM
|
||||
description: 'Return all VIPs to lodge after campfire.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverTom.id,
|
||||
vehicleId: whiteVan.id,
|
||||
masterEventId: campfireNight.id,
|
||||
},
|
||||
});
|
||||
|
||||
// --- DAY 2: TRANSPORT TO EAGLE SCOUT CEREMONY ---
|
||||
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipSusan.id],
|
||||
title: 'Transport to Eagle Scout Ceremony',
|
||||
pickupLocation: 'VIP Lodge',
|
||||
dropoffLocation: 'Main Arena — VIP Entrance',
|
||||
startTime: new Date(jamboreeDay2.getTime() + 8.5 * 60 * 60 * 1000), // 8:30 AM
|
||||
endTime: new Date(jamboreeDay2.getTime() + 8.75 * 60 * 60 * 1000), // 8:45 AM
|
||||
description: 'Roger (3) + Patricia (2) + James (1) + Susan (1) = 7 people. Dr. Baker not attending.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverMaria.id,
|
||||
vehicleId: whiteVan.id,
|
||||
masterEventId: eagleScoutCeremony.id,
|
||||
},
|
||||
});
|
||||
|
||||
// --- DAY 2: TRANSPORT TO FAREWELL BRUNCH ---
|
||||
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id],
|
||||
title: 'Transport to Farewell Brunch',
|
||||
pickupLocation: 'Main Arena / VIP Lodge',
|
||||
dropoffLocation: 'Eagle Lodge',
|
||||
startTime: new Date(jamboreeDay2.getTime() + 11.25 * 60 * 60 * 1000), // 11:15 AM
|
||||
endTime: new Date(jamboreeDay2.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM
|
||||
description: 'Final group transport. 9 people total.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverTom.id,
|
||||
vehicleId: whiteVan.id,
|
||||
masterEventId: farewellBrunch.id,
|
||||
},
|
||||
});
|
||||
|
||||
// --- DAY 2: AIRPORT DEPARTURES ---
|
||||
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipRoger.id],
|
||||
title: 'Airport Drop-off — Roger Mosby',
|
||||
pickupLocation: 'VIP Lodge',
|
||||
dropoffLocation: 'DEN Terminal West',
|
||||
startTime: new Date(jamboreeDay2.getTime() + 14 * 60 * 60 * 1000), // 2:00 PM
|
||||
endTime: new Date(jamboreeDay2.getTime() + 15 * 60 * 60 * 1000), // 3:00 PM
|
||||
description: 'Roger + 2 handlers (3 people) to airport.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverKevin.id,
|
||||
vehicleId: suburban1.id,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.scheduleEvent.create({
|
||||
data: {
|
||||
vipIds: [vipPatricia.id, vipJames.id, vipDrBaker.id],
|
||||
title: 'Airport Drop-off — Hawkins, Whitfield, Baker',
|
||||
pickupLocation: 'VIP Lodge',
|
||||
dropoffLocation: 'DEN Terminal East',
|
||||
startTime: new Date(jamboreeDay2.getTime() + 14.5 * 60 * 60 * 1000), // 2:30 PM
|
||||
endTime: new Date(jamboreeDay2.getTime() + 15.5 * 60 * 60 * 1000), // 3:30 PM
|
||||
description: 'Patricia (2) + James (1) + Dr. Baker (2) = 5 people to airport.',
|
||||
type: EventType.TRANSPORT,
|
||||
status: EventStatus.SCHEDULED,
|
||||
driverId: driverMaria.id,
|
||||
vehicleId: suburban2.id, // 5 people in 6-seat SUV
|
||||
},
|
||||
});
|
||||
|
||||
console.log('✅ Created 15 transport legs linked to master events');
|
||||
|
||||
// =============================================
|
||||
// SUMMARY
|
||||
// =============================================
|
||||
|
||||
console.log('\n🎉 BSA Jamboree seed data created successfully!\n');
|
||||
console.log('VIPs (6):');
|
||||
console.log(' Roger Mosby — Chief Scout Exec (party: 3 = VIP + 2 handlers)');
|
||||
console.log(' Patricia Hawkins — Board Chair (party: 2 = VIP + spouse)');
|
||||
console.log(' James Whitfield III — Major Donor (party: 1 = solo)');
|
||||
console.log(' Dr. Angela Baker — Keynote Speaker (party: 2 = VIP + assistant)');
|
||||
console.log(' Gov. Carlos Martinez — Governor (party: 4 = VIP + security/aide/advance)');
|
||||
console.log(' Susan O\'Malley — Council President (party: 1 = solo)');
|
||||
console.log('\nShared Events (7): Opening Ceremony, VIP Luncheon, Keynote, Donor Meeting, Campfire Night, Eagle Scout Ceremony, Farewell Brunch');
|
||||
console.log('Transport Legs (15): Airport pickups/dropoffs + shuttles to/from each event');
|
||||
console.log('Vehicles (6): 2 Suburbans, 1 Van, 2 Golf Carts, 1 Charter Bus');
|
||||
console.log('Drivers (4): Tom Bradley, Maria Gonzalez, Kevin Park, Lisa Chen');
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user