Allow reordering services even when not all are provided
Modify the service reorder endpoint to handle cases where the client sends a partial list of service IDs, ensuring that unprovided services are appended to the end of the list without causing validation errors.
This commit is contained in:
@@ -87,34 +87,48 @@ router.patch("/services/reorder", requireAdmin, async (req, res): Promise<void>
|
||||
}
|
||||
const { orderedIds } = parsed.data;
|
||||
|
||||
// Validate the provided ids are unique and all reference real
|
||||
// services. We intentionally do NOT require the client to send
|
||||
// every service id — the iPad UI may filter or hide rows, and
|
||||
// forcing a full snapshot caused false 400s ("orderedIds must
|
||||
// contain every service id exactly once"). Any services that
|
||||
// weren't included are pushed to the end of the list so they
|
||||
// remain visible without colliding on sortOrder.
|
||||
const existing = await db
|
||||
.select({ id: servicesTable.id })
|
||||
.from(servicesTable);
|
||||
const existingIds = new Set(existing.map((s) => s.id));
|
||||
|
||||
if (orderedIds.length !== existingIds.size) {
|
||||
res.status(400).json({
|
||||
error: "orderedIds must contain every service id exactly once",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const seen = new Set<number>();
|
||||
for (const id of orderedIds) {
|
||||
if (!existingIds.has(id) || seen.has(id)) {
|
||||
res.status(400).json({
|
||||
error: "orderedIds must contain every service id exactly once",
|
||||
error: "orderedIds contains a duplicate or unknown service id",
|
||||
});
|
||||
return;
|
||||
}
|
||||
seen.add(id);
|
||||
}
|
||||
|
||||
const trailingIds = existing
|
||||
.map((s) => s.id)
|
||||
.filter((id) => !seen.has(id));
|
||||
|
||||
await db.transaction(async (tx) => {
|
||||
for (let i = 0; i < orderedIds.length; i++) {
|
||||
let index = 0;
|
||||
for (const id of orderedIds) {
|
||||
await tx
|
||||
.update(servicesTable)
|
||||
.set({ sortOrder: i })
|
||||
.where(eq(servicesTable.id, orderedIds[i]));
|
||||
.set({ sortOrder: index })
|
||||
.where(eq(servicesTable.id, id));
|
||||
index += 1;
|
||||
}
|
||||
for (const id of trailingIds) {
|
||||
await tx
|
||||
.update(servicesTable)
|
||||
.set({ sortOrder: index })
|
||||
.where(eq(servicesTable.id, id));
|
||||
index += 1;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user