Add functionality to copy weekly shift assignments to the following week
Introduce a new POST API endpoint `/api/shift-assignments/copy-week` to duplicate existing shift assignments and their associated shifts for a specified location and week, automatically adjusting dates by adding 7 days. Replit-Commit-Author: Agent Replit-Commit-Session-Id: e0b5b11c-5b75-4389-8ea9-5f3cd9332f88 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/6d543d2c-20b9-4ea6-93fe-70fe9b1d9f80/e0b5b11c-5b75-4389-8ea9-5f3cd9332f88/EDxr1e6
This commit is contained in:
parent
36bfad3815
commit
0b64fd2f08
123
server/routes.ts
123
server/routes.ts
@ -1337,6 +1337,129 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Copy weekly shift assignments to next week
|
||||||
|
app.post("/api/shift-assignments/copy-week", isAuthenticated, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { weekStart, location } = req.body;
|
||||||
|
|
||||||
|
if (!weekStart || !location) {
|
||||||
|
return res.status(400).json({ message: "Missing required fields: weekStart, location" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse week start date
|
||||||
|
const [year, month, day] = weekStart.split("-").map(Number);
|
||||||
|
if (!year || !month || !day) {
|
||||||
|
return res.status(400).json({ message: "Invalid weekStart format. Expected YYYY-MM-DD" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate week boundaries (Monday to Sunday)
|
||||||
|
const weekStartDate = new Date(year, month - 1, day, 0, 0, 0, 0);
|
||||||
|
const weekEndDate = new Date(year, month - 1, day + 6, 23, 59, 59, 999);
|
||||||
|
|
||||||
|
console.log("📋 Copying weekly shifts:", {
|
||||||
|
weekStart: weekStartDate.toISOString(),
|
||||||
|
weekEnd: weekEndDate.toISOString(),
|
||||||
|
location
|
||||||
|
});
|
||||||
|
|
||||||
|
// Transaction: copy all shifts and assignments
|
||||||
|
const result = await db.transaction(async (tx) => {
|
||||||
|
// 1. Find all shifts in the source week filtered by location
|
||||||
|
const sourceShifts = await tx
|
||||||
|
.select({
|
||||||
|
shift: shifts,
|
||||||
|
site: sites
|
||||||
|
})
|
||||||
|
.from(shifts)
|
||||||
|
.innerJoin(sites, eq(shifts.siteId, sites.id))
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
gte(shifts.startTime, weekStartDate),
|
||||||
|
lte(shifts.startTime, weekEndDate),
|
||||||
|
eq(sites.location, location)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sourceShifts.length === 0) {
|
||||||
|
throw new Error("Nessun turno trovato nella settimana selezionata");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`📋 Found ${sourceShifts.length} shifts to copy`);
|
||||||
|
|
||||||
|
let copiedShiftsCount = 0;
|
||||||
|
let copiedAssignmentsCount = 0;
|
||||||
|
|
||||||
|
// 2. For each shift, copy to next week (+7 days)
|
||||||
|
for (const { shift: sourceShift, site } of sourceShifts) {
|
||||||
|
// Calculate new dates (+7 days)
|
||||||
|
const newStartTime = new Date(sourceShift.startTime);
|
||||||
|
newStartTime.setDate(newStartTime.getDate() + 7);
|
||||||
|
|
||||||
|
const newEndTime = new Date(sourceShift.endTime);
|
||||||
|
newEndTime.setDate(newEndTime.getDate() + 7);
|
||||||
|
|
||||||
|
// Create new shift
|
||||||
|
const [newShift] = await tx
|
||||||
|
.insert(shifts)
|
||||||
|
.values({
|
||||||
|
siteId: sourceShift.siteId,
|
||||||
|
startTime: newStartTime,
|
||||||
|
endTime: newEndTime,
|
||||||
|
status: "planned",
|
||||||
|
vehicleId: sourceShift.vehicleId,
|
||||||
|
notes: sourceShift.notes,
|
||||||
|
})
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
copiedShiftsCount++;
|
||||||
|
|
||||||
|
// 3. Copy all assignments for this shift
|
||||||
|
const sourceAssignments = await tx
|
||||||
|
.select()
|
||||||
|
.from(shiftAssignments)
|
||||||
|
.where(eq(shiftAssignments.shiftId, sourceShift.id));
|
||||||
|
|
||||||
|
for (const sourceAssignment of sourceAssignments) {
|
||||||
|
// Calculate new planned times (+7 days)
|
||||||
|
const newPlannedStart = new Date(sourceAssignment.plannedStartTime);
|
||||||
|
newPlannedStart.setDate(newPlannedStart.getDate() + 7);
|
||||||
|
|
||||||
|
const newPlannedEnd = new Date(sourceAssignment.plannedEndTime);
|
||||||
|
newPlannedEnd.setDate(newPlannedEnd.getDate() + 7);
|
||||||
|
|
||||||
|
// Create new assignment
|
||||||
|
await tx
|
||||||
|
.insert(shiftAssignments)
|
||||||
|
.values({
|
||||||
|
shiftId: newShift.id,
|
||||||
|
guardId: sourceAssignment.guardId,
|
||||||
|
plannedStartTime: newPlannedStart,
|
||||||
|
plannedEndTime: newPlannedEnd,
|
||||||
|
isArmedOnDuty: sourceAssignment.isArmedOnDuty,
|
||||||
|
assignedVehicleId: sourceAssignment.assignedVehicleId,
|
||||||
|
});
|
||||||
|
|
||||||
|
copiedAssignmentsCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { copiedShiftsCount, copiedAssignmentsCount };
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
message: `Settimana copiata con successo: ${result.copiedShiftsCount} turni, ${result.copiedAssignmentsCount} assegnazioni`,
|
||||||
|
copiedShifts: result.copiedShiftsCount,
|
||||||
|
copiedAssignments: result.copiedAssignmentsCount,
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("❌ Error copying weekly shifts:", error);
|
||||||
|
res.status(500).json({
|
||||||
|
message: error.message || "Errore durante la copia dei turni settimanali",
|
||||||
|
error: String(error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Assign guard to site/date with specific time slot (supports multi-day assignments)
|
// Assign guard to site/date with specific time slot (supports multi-day assignments)
|
||||||
app.post("/api/general-planning/assign-guard", isAuthenticated, async (req, res) => {
|
app.post("/api/general-planning/assign-guard", isAuthenticated, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user