Files
2025-10-06 18:11:03 +02:00

244 lines
6.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env tsx
import { config } from 'dotenv';
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from '../src/schemas/database/schema';
import { hashPassword } from '../src/lib/utils/passwordHash';
import { v4 as uuidv4 } from 'uuid';
// Load environment variables from .env file
config();
async function seed() {
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
throw new Error('DATABASE_URL environment variable is not set');
}
console.log('🌱 Starting database seeding...');
const client = postgres(databaseUrl);
const db = drizzle(client, { schema });
try {
// Create admin user
console.log('👤 Creating admin user...');
const adminPasswordHash = await hashPassword('admin123');
const adminUser = await db
.insert(schema.managementUsers)
.values({
firstName: 'Admin',
lastName: 'User',
username: 'admin',
passwordHash: adminPasswordHash,
role: 'ADMIN',
enabled: true
})
.returning()
.onConflictDoNothing();
if (adminUser.length > 0) {
console.log('✅ Admin user created with username: admin, password: admin123');
} else {
console.log('️ Admin user already exists');
}
// Create sample members
console.log('👥 Creating sample members...');
const members = [
{
firstName: 'Max',
lastName: 'Mustermann',
email: 'max.mustermann@example.com',
membershipNumber: 'MEM001',
phoneMobile: '+49123456789',
joinedAt: new Date('2024-01-15')
},
{
firstName: 'Anna',
lastName: 'Schmidt',
email: 'anna.schmidt@example.com',
membershipNumber: 'MEM002',
phoneMobile: '+49987654321',
joinedAt: new Date('2024-02-20')
},
{
firstName: 'Peter',
lastName: 'Müller',
email: 'peter.mueller@example.com',
membershipNumber: 'MEM003',
phoneMobile: '+49555666777',
joinedAt: new Date('2024-03-10')
}
];
const createdMembers = [];
for (const member of members) {
const result = await db
.insert(schema.members)
.values(member)
.returning()
.onConflictDoNothing();
if (result.length > 0) {
createdMembers.push(result[0]);
console.log(`✅ Created member: ${member.firstName} ${member.lastName}`);
}
}
// Create sample RFID cards
console.log('🆔 Creating sample RFID cards...');
const rfidCards = [
{ rfidId: 'ABC123456789', status: 'NEW' as const },
{ rfidId: 'DEF987654321', status: 'NEW' as const },
{ rfidId: 'GHI456789123', status: 'ENGRAVED' as const },
{ rfidId: 'JKL789123456', status: 'NEW' as const },
{ rfidId: 'MNO321654987', status: 'NEW' as const }
];
const createdCards = [];
for (const card of rfidCards) {
const result = await db
.insert(schema.rfidCards)
.values(card)
.returning()
.onConflictDoNothing();
if (result.length > 0) {
createdCards.push(result[0]);
console.log(`✅ Created RFID card: ${card.rfidId} (${card.status})`);
}
}
// Create sample assignments
console.log('🔗 Creating sample card assignments...');
const assignments = [
{
memberId: createdMembers[0]?.id,
cardId: createdCards[0]?.id,
status: 'ASSIGNED' as const,
issuedAt: new Date('2024-01-20')
},
{
memberId: createdMembers[1]?.id,
cardId: createdCards[1]?.id,
status: 'ASSIGNED' as const,
issuedAt: new Date('2024-02-25')
},
{
memberId: createdMembers[2]?.id,
cardId: createdCards[2]?.id,
status: 'ASSIGNED' as const,
issuedAt: new Date('2024-03-15')
}
];
for (const assignment of assignments) {
if (assignment.memberId && assignment.cardId) {
const result = await db
.insert(schema.memberRfidCards)
.values(assignment)
.returning()
.onConflictDoNothing();
if (result.length > 0) {
console.log(
`✅ Assigned card ${createdCards.find((c) => c.id === assignment.cardId)?.rfidId} to ${createdMembers.find((m) => m.id === assignment.memberId)?.firstName} ${createdMembers.find((m) => m.id === assignment.memberId)?.lastName}`
);
}
}
}
// Create sample devices
console.log('📱 Creating sample devices...');
const devices = [
{
name: 'Main Entrance Scanner',
apiKey: 'dev_' + uuidv4().replace(/-/g, ''),
type: 'RFID_SCANNER' as const
},
{
name: 'Office Door Lock',
apiKey: 'dev_' + uuidv4().replace(/-/g, ''),
type: 'LOCK_SYSTEM' as const
}
];
const createdDevices = [];
for (const device of devices) {
const result = await db
.insert(schema.devices)
.values(device)
.returning()
.onConflictDoNothing();
if (result.length > 0) {
createdDevices.push(result[0]);
console.log(`✅ Created device: ${device.name} (${device.type})`);
}
}
// Get all members and devices for access logs
const allMembers = await db.select().from(schema.members);
const allDevices = await db.select().from(schema.devices);
if (allMembers.length === 0 || allDevices.length === 0) {
console.log('⚠️ No members or devices found, skipping access log creation');
} else {
// Create sample access logs for the last 30 days
console.log('📊 Creating sample access logs...');
const accessLogs = [];
const now = new Date();
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
for (let i = 0; i < 30; i++) {
const date = new Date(thirtyDaysAgo.getTime() + i * 24 * 60 * 60 * 1000);
// Random number of accesses per day (5-50)
const accessesPerDay = Math.floor(Math.random() * 46) + 5;
for (let j = 0; j < accessesPerDay; j++) {
const randomMember = allMembers[Math.floor(Math.random() * allMembers.length)];
const randomDevice = allDevices[Math.floor(Math.random() * allDevices.length)];
const randomHour = Math.floor(Math.random() * 24);
const randomMinute = Math.floor(Math.random() * 60);
const accessedAt = new Date(date);
accessedAt.setHours(randomHour, randomMinute, 0, 0);
accessLogs.push({
memberId: randomMember.id,
deviceId: randomDevice.id,
accessedAt,
accessGranted: Math.random() > 0.05 // 95% success rate
});
}
}
for (const log of accessLogs) {
await db.insert(schema.accessLogs).values(log).onConflictDoNothing();
}
console.log(`✅ Created ${accessLogs.length} sample access logs over the last 30 days`);
}
console.log('🎉 Database seeding completed successfully!');
console.log('\n📋 Summary:');
console.log('- Admin user: admin / admin123');
console.log('- Sample members, RFID cards, and assignments created');
console.log('- Sample devices created');
if (allMembers.length > 0 && allDevices.length > 0) {
console.log('- Sample access logs created for chart testing');
}
} catch (error) {
console.error('❌ Error during seeding:', error);
process.exit(1);
} finally {
await client.end();
}
}
seed().catch((error) => {
console.error('❌ Seeding failed:', error);
process.exit(1);
});