Add development tools to reset and seed the application data

Introduces API endpoints `/api/dev/reset-data` (DELETE) and `/api/dev/seed-data` (POST) for clearing and populating the database with sample sites and guards, intended for development and testing purposes.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: e5565357-90e1-419f-b9a8-6ee8394636df
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/6d543d2c-20b9-4ea6-93fe-70fe9b1d9f80/e5565357-90e1-419f-b9a8-6ee8394636df/Jxn533V
This commit is contained in:
marco370 2025-10-22 07:48:24 +00:00
parent 24a1c81d6e
commit 52f3aee8e4
2 changed files with 273 additions and 0 deletions

View File

@ -19,6 +19,10 @@ externalPort = 80
localPort = 33035 localPort = 33035
externalPort = 3001 externalPort = 3001
[[ports]]
localPort = 33123
externalPort = 5173
[[ports]] [[ports]]
localPort = 41343 localPort = 41343
externalPort = 3000 externalPort = 3000

View File

@ -2153,6 +2153,275 @@ export async function registerRoutes(app: Express): Promise<Server> {
} }
}); });
// ============= DEV UTILITIES (Reset & Seed Data) =============
// DELETE all sites and guards (for testing)
app.delete("/api/dev/reset-data", isAuthenticated, async (req, res) => {
try {
// Delete all shift assignments first (foreign key constraints)
await db.delete(shiftAssignments);
// Delete all shifts
await db.delete(shifts);
// Delete all sites
await db.delete(sites);
// Delete all certifications
await db.delete(certifications);
// Delete all guards
await db.delete(guards);
// Delete all vehicles
await db.delete(vehicles);
res.json({
success: true,
message: "Tutti i dati (siti, guardie, turni, veicoli) sono stati eliminati"
});
} catch (error) {
console.error("Error resetting data:", error);
res.status(500).json({ message: "Errore durante reset dati" });
}
});
// Create sample data (3 sites Milano + 3 Roccapiemonte, 10 guards each)
app.post("/api/dev/seed-data", isAuthenticated, async (req, res) => {
try {
// Create service types first
const [serviceTypePresidioFisso] = await db.insert(serviceTypes).values({
name: "Presidio Fisso",
description: "Servizio di presidio fisso con guardia armata",
shiftType: "fixed_post",
fixedPostHours: 24,
}).returning();
const [serviceTypePattuglia] = await db.insert(serviceTypes).values({
name: "Pattuglia Mobile",
description: "Servizio di pattuglia mobile con passaggi programmati",
shiftType: "patrol",
patrolPassages: 4,
}).returning();
// Create 3 sites for Milano
const [siteMilano1] = await db.insert(sites).values({
name: "Banca Centrale Milano",
address: "Via Dante 45, Milano",
city: "Milano",
location: "milano",
serviceTypeId: serviceTypePresidioFisso.id,
shiftType: "fixed_post",
requiresArmed: true,
requiresDriverLicense: false,
minGuardsRequired: 1,
serviceStartTime: "00:00",
serviceEndTime: "24:00",
contractReference: "CTR-MI-001-2025",
contractStartDate: "2025-01-01",
contractEndDate: "2025-12-31",
}).returning();
const [siteMilano2] = await db.insert(sites).values({
name: "Museo Arte Moderna Milano",
address: "Corso Magenta 12, Milano",
city: "Milano",
location: "milano",
serviceTypeId: serviceTypePattuglia.id,
shiftType: "patrol",
requiresArmed: false,
requiresDriverLicense: true,
minGuardsRequired: 1,
serviceStartTime: "08:00",
serviceEndTime: "20:00",
contractReference: "CTR-MI-002-2025",
contractStartDate: "2025-01-01",
contractEndDate: "2025-06-30",
}).returning();
const [siteMilano3] = await db.insert(sites).values({
name: "Centro Commerciale Porta Nuova",
address: "Piazza Gae Aulenti 1, Milano",
city: "Milano",
location: "milano",
serviceTypeId: serviceTypePresidioFisso.id,
shiftType: "fixed_post",
requiresArmed: true,
requiresDriverLicense: false,
minGuardsRequired: 2,
serviceStartTime: "06:00",
serviceEndTime: "22:00",
contractReference: "CTR-MI-003-2025",
contractStartDate: "2025-01-01",
contractEndDate: "2025-12-31",
}).returning();
// Create 3 sites for Roccapiemonte
const [siteRocca1] = await db.insert(sites).values({
name: "Deposito Logistica Roccapiemonte",
address: "Via Industriale 23, Roccapiemonte",
city: "Roccapiemonte",
location: "roccapiemonte",
serviceTypeId: serviceTypePresidioFisso.id,
shiftType: "fixed_post",
requiresArmed: true,
requiresDriverLicense: false,
minGuardsRequired: 1,
serviceStartTime: "00:00",
serviceEndTime: "24:00",
contractReference: "CTR-RC-001-2025",
contractStartDate: "2025-01-01",
contractEndDate: "2025-12-31",
}).returning();
const [siteRocca2] = await db.insert(sites).values({
name: "Cantiere Edile Salerno Nord",
address: "SS 18 km 45, Roccapiemonte",
city: "Roccapiemonte",
location: "roccapiemonte",
serviceTypeId: serviceTypePattuglia.id,
shiftType: "patrol",
requiresArmed: false,
requiresDriverLicense: true,
minGuardsRequired: 1,
serviceStartTime: "18:00",
serviceEndTime: "06:00",
contractReference: "CTR-RC-002-2025",
contractStartDate: "2025-01-15",
contractEndDate: "2025-07-15",
}).returning();
const [siteRocca3] = await db.insert(sites).values({
name: "Stabilimento Farmaceutico",
address: "Via delle Industrie 89, Roccapiemonte",
city: "Roccapiemonte",
location: "roccapiemonte",
serviceTypeId: serviceTypePresidioFisso.id,
shiftType: "fixed_post",
requiresArmed: true,
requiresDriverLicense: false,
minGuardsRequired: 2,
serviceStartTime: "00:00",
serviceEndTime: "24:00",
contractReference: "CTR-RC-003-2025",
contractStartDate: "2025-01-01",
contractEndDate: "2025-12-31",
}).returning();
// Create 10 guards for Milano
const milanNames = [
{ firstName: "Marco", lastName: "Rossi", badgeNumber: "MI-001" },
{ firstName: "Giulia", lastName: "Bianchi", badgeNumber: "MI-002" },
{ firstName: "Luca", lastName: "Ferrari", badgeNumber: "MI-003" },
{ firstName: "Sara", lastName: "Romano", badgeNumber: "MI-004" },
{ firstName: "Andrea", lastName: "Colombo", badgeNumber: "MI-005" },
{ firstName: "Elena", lastName: "Ricci", badgeNumber: "MI-006" },
{ firstName: "Francesco", lastName: "Marino", badgeNumber: "MI-007" },
{ firstName: "Chiara", lastName: "Greco", badgeNumber: "MI-008" },
{ firstName: "Matteo", lastName: "Bruno", badgeNumber: "MI-009" },
{ firstName: "Alessia", lastName: "Gallo", badgeNumber: "MI-010" },
];
for (let i = 0; i < milanNames.length; i++) {
await db.insert(guards).values({
...milanNames[i],
location: "milano",
isArmed: i % 2 === 0, // Alternare armati/non armati
hasDriverLicense: i % 3 === 0, // 1 su 3 con patente
hasFireSafety: true,
hasFirstAid: i % 2 === 1,
phone: `+39 333 ${String(i).padStart(3, '0')}${String(i).padStart(4, '0')}`,
email: `${milanNames[i].firstName.toLowerCase()}.${milanNames[i].lastName.toLowerCase()}@vigilanza.it`,
});
}
// Create 10 guards for Roccapiemonte
const roccaNames = [
{ firstName: "Antonio", lastName: "Esposito", badgeNumber: "RC-001" },
{ firstName: "Maria", lastName: "De Luca", badgeNumber: "RC-002" },
{ firstName: "Giuseppe", lastName: "Russo", badgeNumber: "RC-003" },
{ firstName: "Anna", lastName: "Costa", badgeNumber: "RC-004" },
{ firstName: "Vincenzo", lastName: "Ferrara", badgeNumber: "RC-005" },
{ firstName: "Rosa", lastName: "Gatti", badgeNumber: "RC-006" },
{ firstName: "Salvatore", lastName: "Leone", badgeNumber: "RC-007" },
{ firstName: "Lucia", lastName: "Longo", badgeNumber: "RC-008" },
{ firstName: "Michele", lastName: "Martino", badgeNumber: "RC-009" },
{ firstName: "Carmela", lastName: "Moretti", badgeNumber: "RC-010" },
];
for (let i = 0; i < roccaNames.length; i++) {
await db.insert(guards).values({
...roccaNames[i],
location: "roccapiemonte",
isArmed: i % 2 === 0,
hasDriverLicense: i % 3 === 0,
hasFireSafety: true,
hasFirstAid: i % 2 === 1,
phone: `+39 333 ${String(i + 10).padStart(3, '0')}${String(i + 10).padStart(4, '0')}`,
email: `${roccaNames[i].firstName.toLowerCase()}.${roccaNames[i].lastName.toLowerCase()}@vigilanza.it`,
});
}
// Create 5 vehicles for Milano
const vehiclesMilano = [
{ licensePlate: "MI123AB", brand: "Fiat", model: "Ducato", vehicleType: "van" as const },
{ licensePlate: "MI456CD", brand: "Volkswagen", model: "Transporter", vehicleType: "van" as const },
{ licensePlate: "MI789EF", brand: "Ford", model: "Transit", vehicleType: "van" as const },
{ licensePlate: "MI012GH", brand: "Renault", model: "Kangoo", vehicleType: "car" as const },
{ licensePlate: "MI345IJ", brand: "Opel", model: "Vivaro", vehicleType: "van" as const },
];
for (const vehicle of vehiclesMilano) {
await db.insert(vehicles).values({
...vehicle,
location: "milano",
year: 2022,
status: "available",
});
}
// Create 5 vehicles for Roccapiemonte
const vehiclesRocca = [
{ licensePlate: "SA123AB", brand: "Fiat", model: "Ducato", vehicleType: "van" as const },
{ licensePlate: "SA456CD", brand: "Volkswagen", model: "Caddy", vehicleType: "car" as const },
{ licensePlate: "SA789EF", brand: "Ford", model: "Transit", vehicleType: "van" as const },
{ licensePlate: "SA012GH", brand: "Renault", model: "Master", vehicleType: "van" as const },
{ licensePlate: "SA345IJ", brand: "Peugeot", model: "Partner", vehicleType: "car" as const },
];
for (const vehicle of vehiclesRocca) {
await db.insert(vehicles).values({
...vehicle,
location: "roccapiemonte",
year: 2023,
status: "available",
});
}
res.json({
success: true,
message: "Dati di esempio creati con successo",
summary: {
sites: {
milano: 3,
roccapiemonte: 3,
},
guards: {
milano: 10,
roccapiemonte: 10,
},
vehicles: {
milano: 5,
roccapiemonte: 5,
},
},
});
} catch (error) {
console.error("Error seeding data:", error);
res.status(500).json({ message: "Errore durante creazione dati di esempio" });
}
});
const httpServer = createServer(app); const httpServer = createServer(app);
return httpServer; return httpServer;
} }