batman
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
console.log('Seeding database...');
|
||||
|
||||
// Clean existing data so seed is idempotent
|
||||
await prisma.auditLog.deleteMany();
|
||||
await prisma.remoteCommand.deleteMany();
|
||||
await prisma.openTabSnapshot.deleteMany();
|
||||
await prisma.tabOwnership.deleteMany();
|
||||
await prisma.refreshToken.deleteMany();
|
||||
await prisma.registrationCode.deleteMany();
|
||||
await prisma.device.deleteMany();
|
||||
await prisma.clientUser.deleteMany();
|
||||
await prisma.venue.deleteMany();
|
||||
console.log('Cleared existing data');
|
||||
|
||||
// Create venue
|
||||
const venueId = uuidv4();
|
||||
await prisma.venue.create({
|
||||
data: { id: venueId, name: 'KoolTab Demo Bar' },
|
||||
});
|
||||
console.log(`Created venue: KoolTab Demo Bar (${venueId})`);
|
||||
|
||||
// Create admin user
|
||||
const adminHash = await bcrypt.hash('Admin123!', 10);
|
||||
await prisma.clientUser.create({
|
||||
data: {
|
||||
id: uuidv4(),
|
||||
venueId,
|
||||
email: 'admin@example.com',
|
||||
passwordHash: adminHash,
|
||||
name: 'Eigenaar',
|
||||
role: 'admin',
|
||||
},
|
||||
});
|
||||
console.log('Created admin user: admin@example.com / Admin123!');
|
||||
|
||||
// Create viewer user
|
||||
const viewerHash = await bcrypt.hash('Viewer123!', 10);
|
||||
await prisma.clientUser.create({
|
||||
data: {
|
||||
id: uuidv4(),
|
||||
venueId,
|
||||
email: 'viewer@example.com',
|
||||
passwordHash: viewerHash,
|
||||
name: 'Bartender',
|
||||
role: 'viewer',
|
||||
},
|
||||
});
|
||||
console.log('Created viewer user: viewer@example.com / Viewer123!');
|
||||
|
||||
// Create devices
|
||||
const device1Id = uuidv4();
|
||||
const device2Id = uuidv4();
|
||||
|
||||
const token1 = 'dev_' + crypto.randomBytes(48).toString('base64url');
|
||||
const token2 = 'dev_' + crypto.randomBytes(48).toString('base64url');
|
||||
|
||||
await prisma.device.create({
|
||||
data: {
|
||||
id: device1Id,
|
||||
venueId,
|
||||
name: 'Bar terminal 1',
|
||||
tokenHash: crypto.createHash('sha256').update(token1).digest('hex'),
|
||||
tokenPrefix: token1.substring(0, 8),
|
||||
tokenExpiresAt: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000),
|
||||
lastSeenAt: new Date(Date.now() - 1 * 60 * 1000), // seen 1 minute ago (online)
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.device.create({
|
||||
data: {
|
||||
id: device2Id,
|
||||
venueId,
|
||||
name: 'Bar terminal 2',
|
||||
tokenHash: crypto.createHash('sha256').update(token2).digest('hex'),
|
||||
tokenPrefix: token2.substring(0, 8),
|
||||
tokenExpiresAt: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000),
|
||||
lastSeenAt: new Date(Date.now() - 15 * 60 * 1000), // seen 15 minutes ago (stale)
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Created device: Bar terminal 1 (${device1Id})`);
|
||||
console.log(`Created device: Bar terminal 2 (${device2Id})`);
|
||||
console.log(`Device 1 token: ${token1}`);
|
||||
console.log(`Device 2 token: ${token2}`);
|
||||
|
||||
// Create tab ownership and snapshots for device 1
|
||||
const tabsData = [
|
||||
{ tabId: uuidv4(), customerName: 'Jan', version: 5, totalInCents: 2450, itemCount: 3, reportedAt: new Date(Date.now() - 2 * 60 * 1000) },
|
||||
{ tabId: uuidv4(), customerName: 'Marie', version: 3, totalInCents: 1800, itemCount: 2, reportedAt: new Date(Date.now() - 5 * 60 * 1000) },
|
||||
{ tabId: uuidv4(), customerName: 'Thomas', version: 7, totalInCents: 4200, itemCount: 5, reportedAt: new Date(Date.now() - 3 * 60 * 1000) },
|
||||
{ tabId: uuidv4(), customerName: 'Lisa', version: 2, totalInCents: 900, itemCount: 1, reportedAt: new Date(Date.now() - 4 * 60 * 1000) },
|
||||
];
|
||||
|
||||
for (const tab of tabsData) {
|
||||
await prisma.tabOwnership.create({
|
||||
data: {
|
||||
tabId: tab.tabId,
|
||||
venueId,
|
||||
deviceId: device1Id,
|
||||
lastReportedAt: tab.reportedAt,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.openTabSnapshot.create({
|
||||
data: {
|
||||
deviceId: device1Id,
|
||||
tabId: tab.tabId,
|
||||
customerName: tab.customerName,
|
||||
version: tab.version,
|
||||
totalInCents: tab.totalInCents,
|
||||
itemCount: tab.itemCount,
|
||||
reportedAt: tab.reportedAt,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Create tab ownership and snapshots for device 2 (stale)
|
||||
const staleTabs = [
|
||||
{ tabId: uuidv4(), customerName: 'Emma', version: 4, totalInCents: 3200, itemCount: 4, reportedAt: new Date(Date.now() - 16 * 60 * 1000) },
|
||||
{ tabId: uuidv4(), customerName: 'David', version: 1, totalInCents: 1500, itemCount: 2, reportedAt: new Date(Date.now() - 20 * 60 * 1000) },
|
||||
];
|
||||
|
||||
for (const tab of staleTabs) {
|
||||
await prisma.tabOwnership.create({
|
||||
data: {
|
||||
tabId: tab.tabId,
|
||||
venueId,
|
||||
deviceId: device2Id,
|
||||
lastReportedAt: tab.reportedAt,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.openTabSnapshot.create({
|
||||
data: {
|
||||
deviceId: device2Id,
|
||||
tabId: tab.tabId,
|
||||
customerName: tab.customerName,
|
||||
version: tab.version,
|
||||
totalInCents: tab.totalInCents,
|
||||
itemCount: tab.itemCount,
|
||||
reportedAt: tab.reportedAt,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log('Created 6 open tabs across 2 devices');
|
||||
|
||||
// Create sample commands
|
||||
const now = new Date();
|
||||
|
||||
// Completed command
|
||||
await prisma.remoteCommand.create({
|
||||
data: {
|
||||
id: uuidv4(),
|
||||
venueId,
|
||||
deviceId: device1Id,
|
||||
targetTabId: tabsData[1].tabId,
|
||||
type: 'close_tab',
|
||||
expectedVersion: 3,
|
||||
paymentMethod: 'cash',
|
||||
requestedBy: 'Eigenaar',
|
||||
status: 'completed',
|
||||
result: 'Tab closed successfully',
|
||||
acknowledgedAt: new Date(now.getTime() - 30 * 60 * 1000),
|
||||
createdAt: new Date(now.getTime() - 35 * 60 * 1000),
|
||||
expiresAt: new Date(now.getTime() + 23 * 60 * 60 * 1000),
|
||||
},
|
||||
});
|
||||
|
||||
// Pending command
|
||||
await prisma.remoteCommand.create({
|
||||
data: {
|
||||
id: uuidv4(),
|
||||
venueId,
|
||||
deviceId: device1Id,
|
||||
targetTabId: tabsData[0].tabId,
|
||||
type: 'close_tab',
|
||||
expectedVersion: 5,
|
||||
paymentMethod: 'payconiq',
|
||||
requestedBy: 'Eigenaar',
|
||||
status: 'pending',
|
||||
createdAt: new Date(now.getTime() - 5 * 60 * 1000),
|
||||
expiresAt: new Date(now.getTime() + 23 * 60 * 60 * 1000),
|
||||
},
|
||||
});
|
||||
|
||||
// Failed command
|
||||
await prisma.remoteCommand.create({
|
||||
data: {
|
||||
id: uuidv4(),
|
||||
venueId,
|
||||
deviceId: device2Id,
|
||||
targetTabId: staleTabs[0].tabId,
|
||||
type: 'close_tab',
|
||||
expectedVersion: 4,
|
||||
paymentMethod: 'payment_pending',
|
||||
requestedBy: 'Bartender',
|
||||
status: 'failed',
|
||||
result: 'Tab could not be closed',
|
||||
acknowledgedAt: new Date(now.getTime() - 60 * 60 * 1000),
|
||||
createdAt: new Date(now.getTime() - 65 * 60 * 1000),
|
||||
expiresAt: new Date(now.getTime() + 23 * 60 * 60 * 1000),
|
||||
},
|
||||
});
|
||||
|
||||
// Conflict command
|
||||
await prisma.remoteCommand.create({
|
||||
data: {
|
||||
id: uuidv4(),
|
||||
venueId,
|
||||
deviceId: device1Id,
|
||||
targetTabId: tabsData[2].tabId,
|
||||
type: 'close_tab',
|
||||
expectedVersion: 7,
|
||||
paymentMethod: 'cash',
|
||||
requestedBy: 'Eigenaar',
|
||||
status: 'conflict',
|
||||
result: 'Version mismatch: expected 7, got 8',
|
||||
acknowledgedAt: new Date(now.getTime() - 2 * 60 * 60 * 1000),
|
||||
createdAt: new Date(now.getTime() - 2 * 60 * 60 * 1000 - 5 * 60 * 1000),
|
||||
expiresAt: new Date(now.getTime() + 22 * 60 * 60 * 1000),
|
||||
},
|
||||
});
|
||||
|
||||
console.log('Created sample commands: completed, pending, failed, conflict');
|
||||
|
||||
// Create audit log entries
|
||||
await prisma.auditLog.create({
|
||||
data: {
|
||||
id: uuidv4(),
|
||||
venueId,
|
||||
actorType: 'client_user',
|
||||
actorId: 'admin',
|
||||
action: 'command_created',
|
||||
details: JSON.stringify({ commandId: 'sample', tabId: tabsData[0].tabId }),
|
||||
},
|
||||
});
|
||||
|
||||
console.log('Seeding complete!');
|
||||
console.log('');
|
||||
console.log('Demo credentials:');
|
||||
console.log(' Admin: admin@example.com / Admin123!');
|
||||
console.log(' Viewer: viewer@example.com / Viewer123!');
|
||||
console.log(`\nDevice tokens (for simulator):`);
|
||||
console.log(` Bar terminal 1: ${token1}`);
|
||||
console.log(` Bar terminal 2: ${token2}`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch(console.error)
|
||||
.finally(() => prisma.$disconnect());
|
||||
Reference in New Issue
Block a user