diff --git a/backend/prisma/seed-fix.js b/backend/prisma/seed-fix.js new file mode 100644 index 0000000..a0bf67d --- /dev/null +++ b/backend/prisma/seed-fix.js @@ -0,0 +1,294 @@ +const { PrismaClient, RoomType, SectionType } = require('@prisma/client'); + +const prisma = new PrismaClient(); + +async function main() { + console.log('Seeding database with realistic 3D coordinates...'); + + // 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 + }, + { + name: 'Worker', + permissions: { + tasks: { view: true, complete: 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.run'; + const existingOwner = await prisma.user.findUnique({ where: { email: ownerEmail } }); + + if (!existingOwner) { + await prisma.user.create({ + data: { + email: ownerEmail, + passwordHash: 'password123', + name: 'Travis', + role: 'OWNER', + 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 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}`); + } + } + + // ============================================ + // FACILITY 3D LAYOUT (New) + // ============================================ + + // 1. Property + let property = await prisma.facilityProperty.findFirst(); + if (!property) { + property = await prisma.facilityProperty.create({ + data: { + name: 'Wolfpack Facility', + address: '123 Grow St', + licenseNum: 'CML-123456' + } + }); + console.log('Created Facility Property'); + } + + // 2. Building + let building = await prisma.facilityBuilding.findFirst({ where: { propertyId: property.id } }); + if (!building) { + building = await prisma.facilityBuilding.create({ + data: { + propertyId: property.id, + name: 'Main Building', + code: 'MAIN', + type: 'CULTIVATION' + } + }); + console.log('Created Facility Building'); + } + + // 3. Floor + let floor = await prisma.facilityFloor.findFirst({ where: { buildingId: building.id } }); + if (!floor) { + floor = await prisma.facilityFloor.create({ + data: { + buildingId: building.id, + name: 'Ground Floor', + number: 1, + width: 100, // 100x100 grid + height: 100 + } + }); + console.log('Created Facility Floor'); + } + + // 4. Rooms (Spatial) + const spatialRooms = [ + { + name: 'Veg Room', code: 'VEG', type: RoomType.VEG, + posX: 5, posY: 5, width: 30, height: 40, color: '#4ade80', + sections: [ + { name: 'Rack A', code: 'A', rows: 4, columns: 8, spacing: 2, posX: 2, posY: 2 }, + { name: 'Rack B', code: 'B', rows: 4, columns: 8, spacing: 2, posX: 15, posY: 2 } + ] + }, + { + name: 'Flower Room', code: 'FLO', type: RoomType.FLOWER, + posX: 40, posY: 5, width: 50, height: 60, color: '#a855f7', + sections: [ + { name: 'Bench 1', code: 'B1', rows: 10, columns: 4, spacing: 2, posX: 5, posY: 5 }, + { name: 'Bench 2', code: 'B2', rows: 10, columns: 4, spacing: 2, posX: 20, posY: 5 }, + { name: 'Bench 3', code: 'B3', rows: 10, columns: 4, spacing: 2, posX: 35, posY: 5 } + ] + }, + { + name: 'Dry Room', code: 'DRY', type: RoomType.DRY, + posX: 5, posY: 50, width: 25, height: 25, color: '#f59e0b', + sections: [ + { name: 'Hangers', code: 'H1', rows: 2, columns: 10, spacing: 1, posX: 2, posY: 2 } + ] + } + ]; + + for (const r of spatialRooms) { + let room = await prisma.facilityRoom.findFirst({ + where: { floorId: floor.id, code: r.code } + }); + + if (!room) { + room = await prisma.facilityRoom.create({ + data: { + floorId: floor.id, + name: r.name, + code: r.code, + type: r.type, + posX: r.posX, + posY: r.posY, + width: r.width, + height: r.height, + color: r.color + } + }); + console.log(`Created Spatial Room: ${r.name}`); + } else { + await prisma.facilityRoom.update({ + where: { id: room.id }, + data: { + posX: r.posX, + posY: r.posY, + width: r.width, + height: r.height, + color: r.color + } + }); + console.log(`Updated Spatial Room Coords: ${r.name}`); + } + + // Sections + for (const s of r.sections) { + let section = await prisma.facilitySection.findFirst({ + where: { roomId: room.id, code: s.code } + }); + + if (!section) { + // Create section & positions + const positions = []; + for (let row = 1; row <= s.rows; row++) { + for (let col = 1; col <= s.columns; col++) { + positions.push({ row, column: col, tier: 1, slot: 1 }); + } + } + + section = await prisma.facilitySection.create({ + data: { + roomId: room.id, + name: s.name, + code: s.code, + type: SectionType.RACK, + posX: s.posX, + posY: s.posY, + width: s.columns * s.spacing, + height: s.rows * s.spacing, + rows: s.rows, + columns: s.columns, + spacing: s.spacing, + positions: { + create: positions + } + } + }); + console.log(`Created Section: ${s.name} in ${r.name}`); + } else { + // Update section pos + await prisma.facilitySection.update({ + where: { id: section.id }, + data: { posX: s.posX, posY: s.posY } + }); + } + } + } + + console.log('Seeding complete.'); +} + +main() + .catch((e) => { + console.error(e); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + });