Add patrol routes and related entities for guard scheduling
Introduces new database tables and relations for `patrolRoutes`, `patrolRouteStops`, and updates `shiftAssignments` with new fields like `isArmedOnDuty` and `assignedVehicleId`. Also updates relations for `guards` and `sites`. 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/ZaT6tFl
This commit is contained in:
parent
84cb770877
commit
62b5cb997f
@ -297,6 +297,50 @@ export const shiftAssignments = pgTable("shift_assignments", {
|
||||
// Actual check-in/out times (recorded when guard clocks in/out)
|
||||
checkInTime: timestamp("check_in_time"),
|
||||
checkOutTime: timestamp("check_out_time"),
|
||||
|
||||
// Dotazioni operative per questo turno specifico
|
||||
isArmedOnDuty: boolean("is_armed_on_duty").default(false), // Guardia armata per questo turno
|
||||
assignedVehicleId: varchar("assigned_vehicle_id").references(() => vehicles.id, { onDelete: "set null" }), // Automezzo assegnato
|
||||
});
|
||||
|
||||
// ============= PATROL ROUTES (TURNI PATTUGLIA) =============
|
||||
|
||||
export const patrolRoutes = pgTable("patrol_routes", {
|
||||
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
|
||||
guardId: varchar("guard_id").notNull().references(() => guards.id, { onDelete: "cascade" }),
|
||||
|
||||
// Data e orari del turno pattuglia
|
||||
shiftDate: date("shift_date").notNull(), // Data del turno
|
||||
startTime: varchar("start_time").notNull(), // Orario inizio (HH:MM)
|
||||
endTime: varchar("end_time").notNull(), // Orario fine (HH:MM)
|
||||
|
||||
status: shiftStatusEnum("status").notNull().default("planned"),
|
||||
location: locationEnum("location").notNull(), // Sede di riferimento
|
||||
|
||||
// Dotazioni
|
||||
vehicleId: varchar("vehicle_id").references(() => vehicles.id, { onDelete: "set null" }),
|
||||
isArmedRoute: boolean("is_armed_route").default(false), // Percorso con guardia armata
|
||||
|
||||
notes: text("notes"),
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
updatedAt: timestamp("updated_at").defaultNow(),
|
||||
});
|
||||
|
||||
export const patrolRouteStops = pgTable("patrol_route_stops", {
|
||||
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
|
||||
patrolRouteId: varchar("patrol_route_id").notNull().references(() => patrolRoutes.id, { onDelete: "cascade" }),
|
||||
siteId: varchar("site_id").notNull().references(() => sites.id, { onDelete: "cascade" }),
|
||||
|
||||
sequenceOrder: integer("sequence_order").notNull(), // Ordine nel percorso (1, 2, 3...)
|
||||
estimatedArrivalTime: varchar("estimated_arrival_time"), // Orario stimato arrivo (HH:MM)
|
||||
actualArrivalTime: timestamp("actual_arrival_time"), // Orario effettivo arrivo
|
||||
|
||||
// Check completamento tappa
|
||||
isCompleted: boolean("is_completed").default(false),
|
||||
completedAt: timestamp("completed_at"),
|
||||
|
||||
notes: text("notes"), // Note specifiche per questa tappa
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
});
|
||||
|
||||
// ============= CCNL SETTINGS =============
|
||||
@ -518,6 +562,7 @@ export const guardsRelations = relations(guards, ({ one, many }) => ({
|
||||
}),
|
||||
certifications: many(certifications),
|
||||
shiftAssignments: many(shiftAssignments),
|
||||
patrolRoutes: many(patrolRoutes),
|
||||
constraints: one(guardConstraints),
|
||||
sitePreferences: many(sitePreferences),
|
||||
trainingCourses: many(trainingCourses),
|
||||
@ -549,6 +594,7 @@ export const sitesRelations = relations(sites, ({ one, many }) => ({
|
||||
references: [customers.id],
|
||||
}),
|
||||
shifts: many(shifts),
|
||||
patrolRouteStops: many(patrolRouteStops),
|
||||
preferences: many(sitePreferences),
|
||||
}));
|
||||
|
||||
@ -573,6 +619,33 @@ export const shiftAssignmentsRelations = relations(shiftAssignments, ({ one }) =
|
||||
fields: [shiftAssignments.guardId],
|
||||
references: [guards.id],
|
||||
}),
|
||||
assignedVehicle: one(vehicles, {
|
||||
fields: [shiftAssignments.assignedVehicleId],
|
||||
references: [vehicles.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const patrolRoutesRelations = relations(patrolRoutes, ({ one, many }) => ({
|
||||
guard: one(guards, {
|
||||
fields: [patrolRoutes.guardId],
|
||||
references: [guards.id],
|
||||
}),
|
||||
vehicle: one(vehicles, {
|
||||
fields: [patrolRoutes.vehicleId],
|
||||
references: [vehicles.id],
|
||||
}),
|
||||
stops: many(patrolRouteStops),
|
||||
}));
|
||||
|
||||
export const patrolRouteStopsRelations = relations(patrolRouteStops, ({ one }) => ({
|
||||
patrolRoute: one(patrolRoutes, {
|
||||
fields: [patrolRouteStops.patrolRouteId],
|
||||
references: [patrolRoutes.id],
|
||||
}),
|
||||
site: one(sites, {
|
||||
fields: [patrolRouteStops.siteId],
|
||||
references: [sites.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const notificationsRelations = relations(notifications, ({ one }) => ({
|
||||
@ -731,6 +804,17 @@ export const insertShiftSchema = createInsertSchema(shifts).omit({
|
||||
updatedAt: true,
|
||||
});
|
||||
|
||||
export const insertPatrolRouteSchema = createInsertSchema(patrolRoutes).omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
});
|
||||
|
||||
export const insertPatrolRouteStopSchema = createInsertSchema(patrolRouteStops).omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
});
|
||||
|
||||
// Form schema that accepts datetime strings and transforms to Date
|
||||
export const insertShiftFormSchema = z.object({
|
||||
siteId: z.string().min(1, "Sito obbligatorio"),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user