This commit is contained in:
Rio
2026-06-18 12:16:27 +07:00
parent 7de3a3b4b1
commit 5c0ab92401
84 changed files with 12562 additions and 285 deletions
+79
View File
@@ -0,0 +1,79 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
}
model User {
id Int @id @default(autoincrement())
email String @unique
password String
name String
phone String
role String @default("USER") // USER or ADMIN
createdAt DateTime @default(now())
bookings Booking[]
}
model Route {
id Int @id @default(autoincrement())
departureCity String
arrivalCity String
durationMinutes Int
basePrice Decimal @db.Decimal(10, 2)
createdAt DateTime @default(now())
schedules Schedule[]
}
model Schedule {
id Int @id @default(autoincrement())
routeId Int
route Route @relation(fields: [routeId], references: [id], onDelete: Cascade)
departureTime DateTime
arrivalTime DateTime
vehicleType String // "Toyota HiAce" or "Executive Bus"
capacity Int
price Decimal @db.Decimal(10, 2)
createdAt DateTime @default(now())
bookings Booking[]
}
model Booking {
id Int @id @default(autoincrement())
bookingCode String @unique // e.g. "TRV-XXXXXX"
userId Int?
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
scheduleId Int
schedule Schedule @relation(fields: [scheduleId], references: [id], onDelete: Cascade)
passengerName String
passengerEmail String
passengerPhone String
totalPrice Decimal @db.Decimal(10, 2)
status String @default("PENDING") // PENDING, PAID, CANCELLED
paymentMethod String?
paymentTime DateTime?
createdAt DateTime @default(now())
seats BookingSeat[]
}
model BookingSeat {
id Int @id @default(autoincrement())
bookingId Int
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Cascade)
scheduleId Int
seatNumber String // e.g. "1", "2A", etc.
@@unique([scheduleId, seatNumber])
}
model SystemSetting {
id Int @id @default(autoincrement())
key String @unique
value String @db.Text
}
+129
View File
@@ -0,0 +1,129 @@
const { PrismaClient } = require('@prisma/client');
const { PrismaMariaDb } = require('@prisma/adapter-mariadb');
const bcrypt = require('bcryptjs');
const dotenv = require('dotenv');
dotenv.config({ override: true });
const adapter = new PrismaMariaDb({
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
connectionLimit: 5,
});
const prisma = new PrismaClient({ adapter });
async function main() {
console.log('Seeding database...');
// 1. Clear existing data
await prisma.bookingSeat.deleteMany({});
await prisma.booking.deleteMany({});
await prisma.schedule.deleteMany({});
await prisma.route.deleteMany({});
await prisma.user.deleteMany({});
console.log('Cleared existing data.');
// 2. Create Users
const adminEmail = process.env.ADMIN_EMAIL || 'admin@travel.com';
const adminPass = process.env.ADMIN_PASSWORD || 'admin123';
const hashedPasswordAdmin = await bcrypt.hash(adminPass, 10);
const admin = await prisma.user.create({
data: {
email: adminEmail,
password: hashedPasswordAdmin,
name: 'Super Admin',
phone: '081234567890',
role: 'ADMIN',
},
});
const hashedPasswordUser = await bcrypt.hash('user123', 10);
const user = await prisma.user.create({
data: {
email: 'user@travel.com',
password: hashedPasswordUser,
name: 'John Doe',
phone: '089876543210',
role: 'USER',
},
});
console.log('Created users:', { admin: admin.email, user: user.email });
// 3. Create Routes
const routesData = [
{ departureCity: 'Jakarta', arrivalCity: 'Bandung', durationMinutes: 180, basePrice: 150000 },
{ departureCity: 'Bandung', arrivalCity: 'Jakarta', durationMinutes: 180, basePrice: 150000 },
{ departureCity: 'Jakarta', arrivalCity: 'Bogor', durationMinutes: 90, basePrice: 75000 },
{ departureCity: 'Bogor', arrivalCity: 'Jakarta', durationMinutes: 90, basePrice: 75000 },
];
const routes = [];
for (const r of routesData) {
const route = await prisma.route.create({ data: r });
routes.push(route);
}
console.log(`Created ${routes.length} routes.`);
// 4. Create Schedules for the next 3 days
const today = new Date();
let schedulesCreated = 0;
for (let dayOffset = 0; dayOffset < 3; dayOffset++) {
const targetDate = new Date(today);
targetDate.setDate(today.getDate() + dayOffset);
const dateStr = targetDate.toISOString().split('T')[0];
for (const route of routes) {
// Create some schedules per route
let hours = [];
if (route.departureCity === 'Jakarta' && route.arrivalCity === 'Bandung') {
hours = [7, 10, 13, 16, 19];
} else if (route.departureCity === 'Bandung' && route.arrivalCity === 'Jakarta') {
hours = [7, 10, 13, 16, 19];
} else {
hours = [8, 12, 16];
}
for (let i = 0; i < hours.length; i++) {
const hour = hours[i];
const departureTime = new Date(`${dateStr}T${String(hour).padStart(2, '0')}:00:00.000Z`);
const arrivalTime = new Date(departureTime.getTime() + route.durationMinutes * 60 * 1000);
// Alternate vehicle types
const isHiace = i % 2 === 0;
const vehicleType = isHiace ? 'Toyota HiAce' : 'Executive Bus';
const capacity = isHiace ? 10 : 30;
const price = isHiace ? Number(route.basePrice) : Number(route.basePrice) - 20000;
await prisma.schedule.create({
data: {
routeId: route.id,
departureTime,
arrivalTime,
vehicleType,
capacity,
price,
},
});
schedulesCreated++;
}
}
}
console.log(`Seeded ${schedulesCreated} schedules successfully.`);
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});