import { db } from "./db"; import { users, guards, sites, vehicles, contractParameters, serviceTypes, ccnlSettings } from "@shared/schema"; import { eq } from "drizzle-orm"; import bcrypt from "bcrypt"; async function seed() { console.log("๐ŸŒฑ Avvio seed database multi-sede..."); // Create Service Types console.log("๐Ÿ“ Creazione tipologie di servizi..."); const defaultServiceTypes = [ { code: "fixed_post", label: "Presidio Fisso", description: "Guardia fissa presso una struttura", icon: "Building2", color: "blue", isActive: true }, { code: "patrol", label: "Pattugliamento", description: "Ronde e controlli su area", icon: "Eye", color: "green", isActive: true }, { code: "night_inspection", label: "Ispettorato Notturno", description: "Controlli notturni programmati", icon: "Shield", color: "purple", isActive: true }, { code: "quick_response", label: "Pronto Intervento", description: "Intervento rapido su chiamata", icon: "Zap", color: "orange", isActive: true } ]; for (const serviceType of defaultServiceTypes) { const existing = await db.select().from(serviceTypes).where(eq(serviceTypes.code, serviceType.code)).limit(1); if (existing.length === 0) { await db.insert(serviceTypes).values(serviceType); console.log(` + Creata tipologia: ${serviceType.label}`); } else { console.log(` โœ“ Tipologia esistente: ${serviceType.label}`); } } // Create CCNL Settings console.log("โš™๏ธ Creazione impostazioni CCNL..."); const defaultCcnlSettings = [ { key: "max_hours_per_week", value: "48", description: "Massimo ore lavorative settimanali" }, { key: "max_hours_per_month", value: "190", description: "Massimo ore lavorative mensili" }, { key: "min_rest_hours_between_shifts", value: "11", description: "Ore minime di riposo tra turni" }, { key: "max_night_shifts_consecutive", value: "6", description: "Massimo turni notturni consecutivi" }, { key: "max_days_consecutive", value: "6", description: "Massimo giorni lavorativi consecutivi" }, { key: "min_weekly_rest_hours", value: "24", description: "Ore minime di riposo settimanale" }, { key: "overtime_threshold_week", value: "40", description: "Soglia ore per straordinario settimanale" }, { key: "penalty_if_overtime", value: "true", description: "Penalitร  se supera straordinario" }, ]; for (const setting of defaultCcnlSettings) { const existing = await db.select().from(ccnlSettings).where(eq(ccnlSettings.key, setting.key)).limit(1); if (existing.length === 0) { await db.insert(ccnlSettings).values(setting); console.log(` + Creata impostazione: ${setting.key}`); } else { console.log(` โœ“ Impostazione esistente: ${setting.key}`); } } // Create CCNL contract parameters console.log("๐Ÿ“‹ Creazione parametri contrattuali CCNL..."); const existingParams = await db.select().from(contractParameters).limit(1); if (existingParams.length === 0) { await db.insert(contractParameters).values({ contractType: "CCNL Vigilanza Privata", maxHoursPerDay: 9, maxOvertimePerDay: 2, maxHoursPerWeek: 48, maxOvertimePerWeek: 8, minDailyRestHours: 11, minDailyRestHoursReduced: 9, maxDailyRestReductionsPerMonth: 3, maxDailyRestReductionsPerYear: 20, minWeeklyRestHours: 24, maxNightHoursPerWeek: 40, pauseMinutesIfOver6Hours: 30, holidayPayIncrease: 30, nightPayIncrease: 15, overtimePayIncrease: 20, mealVoucherEnabled: true, mealVoucherAfterHours: 6, mealVoucherAmount: 8 }); console.log(" โœ“ Parametri CCNL creati"); } else { console.log(" โœ“ Parametri CCNL giร  esistenti"); } // Locations const locations = ["roccapiemonte", "milano", "roma"] as const; const locationNames = { roccapiemonte: "Roccapiemonte", milano: "Milano", roma: "Roma" }; // Cleanup existing data (optional - comment out to preserve existing data) // await db.delete(guards); // await db.delete(sites); // await db.delete(vehicles); console.log("๐Ÿ‘ฅ Creazione guardie per ogni sede..."); // Create 10 guards per location const guardNames = [ "Marco Rossi", "Luca Bianchi", "Giuseppe Verdi", "Francesco Romano", "Alessandro Russo", "Andrea Marino", "Matteo Ferrari", "Lorenzo Conti", "Davide Ricci", "Simone Moretti" ]; for (const location of locations) { for (let i = 0; i < 10; i++) { const fullName = guardNames[i]; const [firstName, ...lastNameParts] = fullName.split(" "); const lastName = lastNameParts.join(" "); const email = `${fullName.toLowerCase().replace(" ", ".")}@${location}.vt.alfacom.it`; const badgeNumber = `${location.substring(0, 3).toUpperCase()}${String(i + 1).padStart(3, "0")}`; // Check if user exists const existingUser = await db .select() .from(users) .where(eq(users.email, email)) .limit(1); let userId: string; if (existingUser.length > 0) { userId = existingUser[0].id; console.log(` โœ“ Utente esistente: ${email}`); } else { // Create user const hashedPassword = await bcrypt.hash("guard123", 10); const [newUser] = await db .insert(users) .values({ email, firstName, lastName, passwordHash: hashedPassword, role: "guard" }) .returning(); userId = newUser.id; console.log(` + Creato utente: ${email}`); } // Check if guard exists const existingGuard = await db .select() .from(guards) .where(eq(guards.badgeNumber, badgeNumber)) .limit(1); if (existingGuard.length === 0) { await db.insert(guards).values({ userId, badgeNumber, phoneNumber: `+39 ${330 + i} ${Math.floor(Math.random() * 1000000)}`, location, isArmed: i % 3 === 0, // 1 su 3 รจ armato hasFireSafety: i % 2 === 0, // 1 su 2 ha antincendio hasFirstAid: i % 4 === 0, // 1 su 4 ha primo soccorso hasDriverLicense: i % 2 === 1, // 1 su 2 ha patente languages: i === 0 ? ["italiano", "inglese"] : ["italiano"] }); console.log(` + Creata guardia: ${badgeNumber} - ${name} (${locationNames[location]})`); } else { console.log(` โœ“ Guardia esistente: ${badgeNumber}`); } } } console.log("\n๐Ÿข Creazione clienti per ogni sede..."); // Create 10 clients per location const companyNames = [ "Banca Centrale", "Ospedale San Marco", "Centro Commerciale Europa", "Uffici Postali", "Museo Arte Moderna", "Palazzo Comunale", "Stazione Ferroviaria", "Aeroporto Internazionale", "Universitร  Statale", "Tribunale Civile" ]; for (const location of locations) { for (let i = 0; i < 10; i++) { const companyName = companyNames[i]; const email = `${companyName.toLowerCase().replace(/ /g, ".")}@${location}.clienti.vt.it`; // Check if client user exists const existingClient = await db .select() .from(users) .where(eq(users.email, email)) .limit(1); let clientId: string; if (existingClient.length > 0) { clientId = existingClient[0].id; console.log(` โœ“ Cliente esistente: ${email}`); } else { const hashedPassword = await bcrypt.hash("client123", 10); const [newClient] = await db .insert(users) .values({ email, firstName: companyName, lastName: locationNames[location], passwordHash: hashedPassword, role: "client" }) .returning(); clientId = newClient.id; console.log(` + Creato cliente: ${email}`); } // Check if site exists const siteName = `${companyName} - ${locationNames[location]}`; const existingSite = await db .select() .from(sites) .where(eq(sites.name, siteName)) .limit(1); if (existingSite.length === 0) { const shiftTypes = ["fixed_post", "patrol", "night_inspection", "quick_response"] as const; await db.insert(sites).values({ name: siteName, address: `Via ${companyName} ${i + 1}, ${locationNames[location]}`, clientId, location, shiftType: shiftTypes[i % 4], minGuards: Math.floor(Math.random() * 3) + 1, requiresArmed: i % 3 === 0, requiresDriverLicense: i % 4 === 0, isActive: true }); console.log(` + Creato sito: ${siteName}`); } else { console.log(` โœ“ Sito esistente: ${siteName}`); } } } console.log("\n๐Ÿš— Creazione automezzi per ogni sede..."); // Create vehicles per location const vehicleBrands = [ { brand: "Fiat", model: "Punto", type: "car" }, { brand: "Volkswagen", model: "Polo", type: "car" }, { brand: "Ford", model: "Transit", type: "van" }, { brand: "Mercedes", model: "Sprinter", type: "van" }, { brand: "BMW", model: "GS 750", type: "motorcycle" }, ] as const; for (const location of locations) { for (let i = 0; i < 5; i++) { const vehicle = vehicleBrands[i]; const licensePlate = `${location.substring(0, 2).toUpperCase()}${String(Math.floor(Math.random() * 1000)).padStart(3, "0")}${String.fromCharCode(65 + Math.floor(Math.random() * 26))}${String.fromCharCode(65 + Math.floor(Math.random() * 26))}`; // Check if vehicle exists const existingVehicle = await db .select() .from(vehicles) .where(eq(vehicles.licensePlate, licensePlate)) .limit(1); if (existingVehicle.length === 0) { await db.insert(vehicles).values({ licensePlate, brand: vehicle.brand, model: vehicle.model, vehicleType: vehicle.type, year: 2018 + Math.floor(Math.random() * 6), location, status: i === 0 ? "in_use" : "available", mileage: Math.floor(Math.random() * 100000) + 10000 }); console.log(` + Creato automezzo: ${licensePlate} - ${vehicle.brand} ${vehicle.model} (${locationNames[location]})`); } else { console.log(` โœ“ Automezzo esistente: ${licensePlate}`); } } } console.log("\nโœ… Seed completato!"); console.log(` ๐Ÿ“Š Riepilogo: - 30 guardie totali (10 per sede) - 30 siti/clienti totali (10 per sede) - 15 automezzi totali (5 per sede) ๐Ÿ” Credenziali: - Guardie: *.guardia@[sede].vt.alfacom.it / guard123 - Clienti: *@[sede].clienti.vt.it / client123 - Admin: admin@vt.alfacom.it / admin123 `); process.exit(0); } seed().catch((error) => { console.error("โŒ Errore seed:", error); process.exit(1); });