Phase 8: Visitor Management - Visitor/VisitorLog/AccessZone models - Check-in/out with badge generation - Zone occupancy tracking - Kiosk and management pages Phase 9: Messaging & Communication - Announcements with priority levels - Acknowledgement tracking - Shift notes for team handoffs - AnnouncementBanner component Phase 10: Compliance & Audit Trail - Immutable AuditLog model - Document versioning and approval workflow - Acknowledgement tracking for SOPs - CSV export for audit logs Phase 11: Accessibility & i18n - WCAG 2.1 AA compliance utilities - react-i18next with EN/ES translations - User preferences context (theme, font size, etc) - High contrast and reduced motion support Phase 12: Hardware Integration - QR code generation for batches/plants/visitors - Printable label system - Visitor badge printing Phase 13: Advanced Features - Environmental monitoring (sensors, readings, alerts) - Financial tracking (transactions, P&L reports) - AI/ML insights (yield predictions, anomaly detection)
151 lines
4.2 KiB
JavaScript
151 lines
4.2 KiB
JavaScript
const { PrismaClient, RoomType } = require('@prisma/client');
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
async function main() {
|
|
console.log('Seeding database (JS)...');
|
|
|
|
// Seed Roles
|
|
const rolesData = [
|
|
{
|
|
name: 'Facility Owner',
|
|
permissions: { admin: true },
|
|
isSystem: true
|
|
},
|
|
{
|
|
name: 'Manager',
|
|
permissions: {
|
|
users: { manage: true },
|
|
tasks: { manage: true },
|
|
inventory: { manage: true }
|
|
},
|
|
isSystem: true
|
|
},
|
|
{
|
|
name: 'Grower',
|
|
permissions: {
|
|
tasks: { view: true, complete: true },
|
|
inventory: { view: true }
|
|
},
|
|
isSystem: true
|
|
}
|
|
];
|
|
|
|
for (const r of rolesData) {
|
|
const existing = await prisma.role.findUnique({ where: { name: r.name } });
|
|
if (!existing) {
|
|
await prisma.role.create({ data: r });
|
|
console.log(`Created Role: ${r.name}`);
|
|
}
|
|
}
|
|
|
|
const ownerRole = await prisma.role.findUnique({ where: { name: 'Facility Owner' } });
|
|
|
|
// Create Owner
|
|
const ownerEmail = 'admin@runfoo.com';
|
|
const existingOwner = await prisma.user.findUnique({ where: { email: ownerEmail } });
|
|
|
|
if (!existingOwner) {
|
|
await prisma.user.create({
|
|
data: {
|
|
email: ownerEmail,
|
|
passwordHash: 'password123',
|
|
name: 'Travis',
|
|
role: 'OWNER', // Enum fallback
|
|
roleId: ownerRole?.id,
|
|
rate: 100.00
|
|
}
|
|
});
|
|
console.log('Created Owner: Travis (admin@runfoo.com)');
|
|
} else {
|
|
// Update existing owner to have roleId if missing
|
|
if (!existingOwner.roleId && ownerRole) {
|
|
await prisma.user.update({
|
|
where: { email: ownerEmail },
|
|
data: { roleId: ownerRole.id, name: 'Travis' }
|
|
});
|
|
console.log('Updated Owner permissions');
|
|
}
|
|
}
|
|
|
|
// Create Default Rooms
|
|
const rooms = [
|
|
{ name: 'Veg Room 1', type: RoomType.VEG, sqft: 1200 },
|
|
{ name: 'Flower Room A', type: RoomType.FLOWER, sqft: 2500 },
|
|
{ name: 'Flower Room B', type: RoomType.FLOWER, sqft: 2500 },
|
|
{ name: 'Dry Room', type: RoomType.DRY, sqft: 800 },
|
|
];
|
|
|
|
for (const r of rooms) {
|
|
const existing = await prisma.room.findFirst({ where: { name: r.name } });
|
|
if (!existing) {
|
|
await prisma.room.create({ data: r });
|
|
console.log(`Created Room: ${r.name}`);
|
|
}
|
|
}
|
|
|
|
// Create Default Supplies
|
|
const supplies = [
|
|
{
|
|
name: 'Nitrile Gloves (L)',
|
|
category: 'PPE',
|
|
quantity: 5,
|
|
minThreshold: 10,
|
|
unit: 'box',
|
|
location: 'Ante Room',
|
|
vendor: 'Uline',
|
|
productUrl: 'https://uline.com'
|
|
},
|
|
{
|
|
name: 'Hypochlorous Acid',
|
|
category: 'CLEANING',
|
|
quantity: 12,
|
|
minThreshold: 5,
|
|
unit: 'gallon',
|
|
location: 'Janitor Clonet',
|
|
vendor: 'Athena'
|
|
},
|
|
{
|
|
name: 'Rockwool Cubes 4"',
|
|
category: 'OTHER',
|
|
quantity: 450,
|
|
minThreshold: 200,
|
|
unit: 'cube',
|
|
location: 'Veg Storage',
|
|
vendor: 'GrowGen'
|
|
},
|
|
{
|
|
name: 'Trimmers (Fiskars)',
|
|
category: 'MAINTENANCE',
|
|
quantity: 15,
|
|
minThreshold: 15,
|
|
unit: 'pair',
|
|
location: 'Trim Jail',
|
|
vendor: 'Amazon'
|
|
}
|
|
];
|
|
|
|
for (const s of supplies) {
|
|
const existing = await prisma.supplyItem.findFirst({ where: { name: s.name } });
|
|
if (!existing) {
|
|
await prisma.supplyItem.create({
|
|
data: {
|
|
...s,
|
|
category: s.category
|
|
}
|
|
});
|
|
console.log(`Created Supply: ${s.name}`);
|
|
}
|
|
}
|
|
|
|
console.log('Seeding complete.');
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|