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:
2026-02-04 00:03:49 +01:00
parent 8e8bbad3fc
commit a6b639d5f4

View File

@@ -3,145 +3,153 @@ import { PrismaClient, Role, Department, ArrivalMode, EventType, EventStatus, Ve
const prisma = new PrismaClient(); const prisma = new PrismaClient();
async function main() { 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.scheduleEvent.deleteMany({});
await prisma.flight.deleteMany({}); await prisma.flight.deleteMany({});
await prisma.vehicle.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.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: { data: {
auth0Id: 'auth0|admin-sample-id', name: 'Black Suburban #1',
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',
type: VehicleType.SUV, type: VehicleType.SUV,
licensePlate: 'ABC-1234', licensePlate: 'BSA-001',
seatCapacity: 6, seatCapacity: 6,
status: VehicleStatus.AVAILABLE, 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({ const whiteVan = await prisma.vehicle.create({
data: { data: {
name: 'White Sprinter Van', name: 'White 15-Passenger Van',
type: VehicleType.VAN, type: VehicleType.VAN,
licensePlate: 'XYZ-5678', licensePlate: 'BSA-003',
seatCapacity: 12, seatCapacity: 14,
status: VehicleStatus.AVAILABLE, 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: { data: {
name: 'Blue Camry', name: 'Golf Cart A',
type: VehicleType.SEDAN, type: VehicleType.GOLF_CART,
licensePlate: 'DEF-9012', licensePlate: 'GC-A',
seatCapacity: 4, seatCapacity: 4,
status: VehicleStatus.AVAILABLE, 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: { data: {
name: 'Gray Charter Bus', name: 'Golf Cart B',
type: VehicleType.BUS, type: VehicleType.GOLF_CART,
licensePlate: 'BUS-0001', licensePlate: 'GC-B',
seatCapacity: 40, seatCapacity: 4,
status: VehicleStatus.AVAILABLE, 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'); const charterBus = await prisma.vehicle.create({
// Create sample drivers
const driver1 = await prisma.driver.create({
data: { data: {
name: 'John Smith', name: 'Charter Bus',
phone: '+1 (555) 123-4567', type: VehicleType.BUS,
department: Department.OFFICE_OF_DEVELOPMENT, 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: { data: {
name: 'Jane Doe', name: 'Tom Bradley',
phone: '+1 (555) 987-6543', phone: '+1 (555) 100-0001',
department: Department.ADMIN, department: Department.ADMIN,
}, },
}); });
const driver3 = await prisma.driver.create({ const driverMaria = await prisma.driver.create({
data: { data: {
name: 'Amanda Washington', name: 'Maria Gonzalez',
phone: '+1 (555) 234-5678', phone: '+1 (555) 100-0002',
department: Department.OFFICE_OF_DEVELOPMENT,
},
});
const driver4 = await prisma.driver.create({
data: {
name: 'Michael Thompson',
phone: '+1 (555) 876-5432',
department: Department.ADMIN, department: Department.ADMIN,
}, },
}); });
console.log('✅ Created sample drivers'); const driverKevin = await prisma.driver.create({
// Create sample VIPs
const vip1 = await prisma.vIP.create({
data: { data: {
name: 'Dr. Robert Johnson', name: 'Kevin Park',
organization: 'Tech Corporation', 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, department: Department.OFFICE_OF_DEVELOPMENT,
arrivalMode: ArrivalMode.FLIGHT, arrivalMode: ArrivalMode.FLIGHT,
airportPickup: true, airportPickup: true,
venueTransport: 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: { flights: {
create: [ create: [
{ {
flightNumber: 'AA123', flightNumber: 'UA1142',
flightDate: new Date('2026-02-15'), flightDate: new Date('2026-02-05'),
segment: 1, segment: 1,
departureAirport: 'JFK', departureAirport: 'IAD',
arrivalAirport: 'LAX', arrivalAirport: 'DEN',
scheduledDeparture: new Date('2026-02-15T08:00:00'), scheduledDeparture: new Date('2026-02-05T07:00:00'),
scheduledArrival: new Date('2026-02-15T11:30:00'), scheduledArrival: new Date('2026-02-05T09:15:00'),
status: 'scheduled', 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: { data: {
name: 'Ms. Sarah Williams', name: 'Patricia Hawkins',
organization: 'Global Foundation', 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, department: Department.ADMIN,
arrivalMode: ArrivalMode.SELF_DRIVING, arrivalMode: ArrivalMode.SELF_DRIVING,
expectedArrival: new Date('2026-02-16T14:00:00'), expectedArrival: new Date('2026-02-05T13:00:00'),
airportPickup: false, airportPickup: false,
venueTransport: true, 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: { data: {
name: 'Emily Richardson (Harvard University)', name: 'Susan O\'Malley',
organization: 'Harvard University', organization: 'Denver Area Council BSA',
department: Department.OFFICE_OF_DEVELOPMENT, department: Department.ADMIN,
arrivalMode: ArrivalMode.FLIGHT, arrivalMode: ArrivalMode.SELF_DRIVING,
airportPickup: true, expectedArrival: new Date('2026-02-05T08:00:00'),
airportPickup: false,
venueTransport: true, 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: { data: {
name: 'David Chen (Stanford)', vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipGovMartinez.id, vipSusan.id],
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],
title: 'Opening Ceremony', title: 'Opening Ceremony',
location: 'Main Stage', location: 'Main Arena',
startTime: new Date('2026-02-15T10:00:00'), startTime: new Date(jamboreeDay1.getTime() + 10 * 60 * 60 * 1000), // 10:00 AM
endTime: new Date('2026-02-15T11:30:00'), endTime: new Date(jamboreeDay1.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM
description: 'Welcome and opening remarks', description: 'National anthem, color guard, welcome remarks by Chief Scout Executive. All VIPs seated in reserved section.',
type: EventType.EVENT, type: EventType.EVENT,
status: EventStatus.SCHEDULED, status: EventStatus.SCHEDULED,
}, },
}); });
// Lunch - Day 1 (all VIPs) const vipLuncheon = await prisma.scheduleEvent.create({
await prisma.scheduleEvent.create({
data: { data: {
vipIds: [vip1.id, vip2.id, vip3.id, vip4.id], vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipGovMartinez.id, vipSusan.id],
title: 'Lunch - Day 1', title: 'VIP Luncheon',
location: 'Main Dining Hall', location: 'Eagle Lodge Private Dining',
startTime: new Date('2026-02-15T12:00:00'), startTime: new Date(jamboreeDay1.getTime() + 12 * 60 * 60 * 1000), // 12:00 PM
endTime: new Date('2026-02-15T13:30:00'), endTime: new Date(jamboreeDay1.getTime() + 13.5 * 60 * 60 * 1000), // 1:30 PM
description: 'Day 1 lunch for all attendees', description: 'Private luncheon for VIP guests and BSA leadership. Seated service.',
type: EventType.MEAL, type: EventType.MEAL,
status: EventStatus.SCHEDULED, status: EventStatus.SCHEDULED,
}, },
}); });
// Campfire Night (all VIPs) const keynoteAddress = await prisma.scheduleEvent.create({
await prisma.scheduleEvent.create({
data: { data: {
vipIds: [vip1.id, vip2.id, vip3.id, vip4.id], vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id],
title: 'Campfire Night', title: 'Keynote Address — Dr. Baker',
location: 'Camp Amphitheater', location: 'Main Arena',
startTime: new Date('2026-02-15T20:00:00'), startTime: new Date(jamboreeDay1.getTime() + 14 * 60 * 60 * 1000), // 2:00 PM
endTime: new Date('2026-02-15T22:00:00'), endTime: new Date(jamboreeDay1.getTime() + 15.5 * 60 * 60 * 1000), // 3:30 PM
description: 'Evening campfire and networking', description: 'Dr. Angela Baker delivers keynote on "Adventure and Discovery." VIPs in reserved front section.',
type: EventType.EVENT, type: EventType.EVENT,
status: EventStatus.SCHEDULED, status: EventStatus.SCHEDULED,
notes: 'Gov. Martinez departs before keynote — not attending this one.',
}, },
}); });
// Private meeting - just Dr. Johnson and Ms. Williams const donorMeeting = await prisma.scheduleEvent.create({
await prisma.scheduleEvent.create({
data: { data: {
vipIds: [vip1.id, vip2.id], vipIds: [vipJames.id, vipPatricia.id, vipRoger.id],
title: 'Donor Meeting', title: 'Donor Strategy Meeting',
location: 'Conference Room A', location: 'Eagle Lodge Conference Room',
startTime: new Date('2026-02-15T14:00:00'), startTime: new Date(jamboreeDay1.getTime() + 16 * 60 * 60 * 1000), // 4:00 PM
endTime: new Date('2026-02-15T15:00:00'), endTime: new Date(jamboreeDay1.getTime() + 17 * 60 * 60 * 1000), // 5:00 PM
description: 'Private meeting with development team', description: 'Private meeting: Whitfield Foundation partnership discussion with BSA leadership.',
type: EventType.MEETING, type: EventType.MEETING,
status: EventStatus.SCHEDULED, 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!'); // Day 2 shared events
console.log('\nSample Users:'); const eagleScoutCeremony = await prisma.scheduleEvent.create({
console.log('- Admin: admin@example.com'); data: {
console.log('- Coordinator: coordinator@example.com'); vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipSusan.id],
console.log('\nSample VIPs:'); title: 'Eagle Scout Recognition Ceremony',
console.log('- Dr. Robert Johnson (Flight arrival)'); location: 'Main Arena',
console.log('- Ms. Sarah Williams (Self-driving)'); startTime: new Date(jamboreeDay2.getTime() + 9 * 60 * 60 * 1000), // 9:00 AM
console.log('- Emily Richardson (Harvard University)'); endTime: new Date(jamboreeDay2.getTime() + 11 * 60 * 60 * 1000), // 11:00 AM
console.log('- David Chen (Stanford)'); description: 'Honoring 200+ new Eagle Scouts. James Whitfield giving remarks as Eagle Scout alumnus.',
console.log('\nSample Drivers:'); type: EventType.EVENT,
console.log('- John Smith'); status: EventStatus.SCHEDULED,
console.log('- Jane Doe'); },
console.log('- Amanda Washington'); });
console.log('- Michael Thompson');
console.log('\nSample Vehicles:'); const farewellBrunch = await prisma.scheduleEvent.create({
console.log('- Black Suburban (SUV, 6 seats)'); data: {
console.log('- White Sprinter Van (Van, 12 seats)'); vipIds: [vipRoger.id, vipPatricia.id, vipJames.id, vipDrBaker.id, vipSusan.id],
console.log('- Blue Camry (Sedan, 4 seats)'); title: 'Farewell Brunch',
console.log('- Gray Charter Bus (Bus, 40 seats)'); location: 'Eagle Lodge Private Dining',
console.log('\nSchedule Tasks (Multi-VIP Examples):'); startTime: new Date(jamboreeDay2.getTime() + 11.5 * 60 * 60 * 1000), // 11:30 AM
console.log('- 3 VIPs sharing SUV to Campfire (3/6 seats)'); endTime: new Date(jamboreeDay2.getTime() + 13 * 60 * 60 * 1000), // 1:00 PM
console.log('- 2 VIPs sharing sedan to Lunch (2/4 seats)'); description: 'Final meal together before departures. Thank-you gifts distributed.',
console.log('- 4 VIPs in van to Conference (4/12 seats)'); type: EventType.MEAL,
console.log('- 1 VIP solo in sedan from Airport (1/4 seats)'); 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() main()