Skip to content

Commit f729ac6

Browse files
Agendar de ultimo el parqueadero 014
1 parent 8b2688a commit f729ac6

1 file changed

Lines changed: 128 additions & 109 deletions

File tree

src/Hooks/useReservar.ts

Lines changed: 128 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -160,123 +160,142 @@ export function useReservar(
160160
[reservationsSvc]
161161
);
162162

163-
const reservar = React.useCallback(
164-
async ({ vehicle, turn, dateISO }: ReserveArgs): Promise<ReserveResult> => {
165-
// 0) Validación por tipo de turno respecto al usuario
163+
const reservar = React.useCallback(
164+
async ({ vehicle, turn, dateISO }: ReserveArgs): Promise<ReserveResult> => {
165+
if (turn === 'Dia') {
166+
if (await hasActiveReservationAnyTurnSameDay(userMail, dateISO)) {
167+
return {
168+
ok: false,
169+
message: `No puedes reservar día completo: ya tienes una reserva activa para el ${dateISO}.`,
170+
};
171+
}
172+
} else {
173+
if (await hasActiveReservationSameDay(userMail, dateISO, turn)) {
174+
return {
175+
ok: false,
176+
message: `No puedes reservar: ya tienes una reserva activa para el ${dateISO} en el turno de la ${turn}.`,
177+
};
178+
}
179+
}
180+
181+
const slotsFilter = [
182+
`(fields/Activa eq 'Activa')`,
183+
`fields/TipoCelda eq '${vehicle}'`,
184+
`fields/Itinerancia eq 'Empleado Itinerante'`,
185+
].join(' and ');
186+
187+
const slots = await slotsSvc.getAll({ filter: slotsFilter, top: 2000 });
188+
if (!Array.isArray(slots) || slots.length === 0) {
189+
return { ok: false, message: `No existen celdas activas para ${vehicle}.` };
190+
}
191+
192+
//IDs de celdas que van siempre al final
193+
const LAST_GROUP_IDS = new Set<number>([5]);
194+
195+
const getSlotId = (slot: unknown): number | null => {
196+
const rslot = slot as Record<string, unknown>;
197+
const raw =
198+
(rslot['ID'] as number | string | undefined) ??
199+
(rslot['Id'] as number | string | undefined) ??
200+
(rslot['id'] as number | string | undefined);
201+
return raw == null ? null : Number(raw);
202+
};
203+
204+
// 🔹 Particionamos: primero normales, luego “último grupo”
205+
const primarySlots: unknown[] = [];
206+
const lastGroupSlots: unknown[] = [];
207+
208+
for (const s of slots) {
209+
const id = getSlotId(s);
210+
if (id == null) continue;
211+
212+
if (LAST_GROUP_IDS.has(id)) lastGroupSlots.push(s);
213+
else primarySlots.push(s);
214+
}
215+
216+
const orderedSlots = [...primarySlots, ...lastGroupSlots];
217+
218+
console.log('[useReservar] Slots ordenados: ', orderedSlots);
219+
220+
// 2) Turnos a validar capacidad
221+
const turnsToCheck: Exclude<TurnType, 'Dia'>[] =
222+
turn === 'Dia' ? ['Manana', 'Tarde'] : [turn as Exclude<TurnType, 'Dia'>];
223+
224+
// 👉 Ahora iteramos sobre orderedSlots en vez de slots
225+
for (const slot of orderedSlots) {
226+
const rslot = slot as Record<string, unknown>;
227+
const slotId =
228+
(rslot['ID'] as number | string | undefined) ??
229+
(rslot['Id'] as number | string | undefined) ??
230+
(rslot['id'] as number | string | undefined);
231+
const code =
232+
(rslot['Title'] as string | undefined) ??
233+
(rslot['Code'] as string | undefined) ??
234+
(rslot['Name'] as string | undefined) ??
235+
slotId;
236+
237+
if (slotId == null) continue;
238+
239+
let available = true;
240+
166241
if (turn === 'Dia') {
167-
// Día completo: bloquear si ya existe cualquier reserva del usuario ese día
168-
if (await hasActiveReservationAnyTurnSameDay(userMail, dateISO)) {
169-
return {
170-
ok: false,
171-
message: `No puedes reservar día completo: ya tienes una reserva activa para el ${dateISO}.`,
172-
};
173-
}
242+
const any = await countReservations(slotId, dateISO, ['Manana', 'Tarde', 'Día completo']);
243+
if (any > 0) available = false;
174244
} else {
175-
// Mañana/Tarde: bloquear si el usuario ya tiene reserva en ese mismo turno o un 'Día completo'
176-
if (await hasActiveReservationSameDay(userMail, dateISO, turn)) {
177-
return {
178-
ok: false,
179-
message: `No puedes reservar: ya tienes una reserva activa para el ${dateISO} en el turno de la ${turn}.`,
180-
};
245+
for (const t of turnsToCheck) {
246+
const count = await countReservations(slotId, dateISO, [t, 'Día completo']);
247+
if (count >= 1) {
248+
available = false;
249+
break;
250+
}
181251
}
182252
}
183253

184-
// 1) Traer celdas activas del tipo solicitado (itinerantes)
185-
const slotsFilter = [
186-
`(fields/Activa eq 'Activa')`,
187-
`fields/TipoCelda eq '${vehicle}'`,
188-
`fields/Itinerancia eq 'Empleado Itinerante'`,
189-
].join(' and ');
254+
if (!available) continue;
190255

191-
const slots = await slotsSvc.getAll({ filter: slotsFilter, top: 2000 });
192-
if (!Array.isArray(slots) || slots.length === 0) {
193-
return { ok: false, message: `No existen celdas activas para ${vehicle}.` };
194-
}
195-
console.log('[useReservar] Slots: ', slots);
196-
197-
// 2) Turnos a validar capacidad (para 'Dia' valida mañana y tarde)
198-
const turnsToCheck: Exclude<TurnType, 'Dia'>[] =
199-
turn === 'Dia' ? ['Manana', 'Tarde'] : [turn as Exclude<TurnType, 'Dia'>];
200-
201-
for (const slot of slots) {
202-
const rslot = slot as Record<string, unknown>;
203-
const slotId =
204-
(rslot['ID'] as number | string | undefined) ??
205-
(rslot['Id'] as number | string | undefined) ??
206-
(rslot['id'] as number | string | undefined);
207-
const code =
208-
(rslot['Title'] as string | undefined) ??
209-
(rslot['Code'] as string | undefined) ??
210-
(rslot['Name'] as string | undefined) ??
211-
slotId;
212-
213-
if (slotId == null) continue;
214-
215-
// 3) Validar disponibilidad (capacidad por turno = 1, sin distinción por tipo de vehículo)
216-
let available = true;
217-
218-
if (turn === 'Dia') {
219-
// Debe estar libre en ambos turnos y sin 'Día completo' previo
220-
const any = await countReservations(slotId, dateISO, ['Manana', 'Tarde', 'Día completo']);
221-
if (any > 0) available = false;
222-
} else {
223-
// Mañana/Tarde: considera también 'Día completo' como bloqueo del turno
224-
for (const t of turnsToCheck) {
225-
const count = await countReservations(slotId, dateISO, [t, 'Día completo']);
226-
if (count >= 1) { available = false; break; }
227-
}
228-
}
256+
const turnValue: TurnDb = turn === 'Dia' ? 'Día completo' : (turn as TurnDb);
229257

230-
if (!available) continue;
231-
232-
// 4) Crear **una** sola reserva en la primera celda disponible
233-
const turnValue: TurnDb = (turn === 'Dia' ? 'Día completo' : (turn as TurnDb));
234-
235-
try {
236-
const payload = {
237-
Title: userMail,
238-
Date: dateISO,
239-
Turn: turnValue,
240-
SpotIdLookupId: Number(slotId),
241-
VehicleType: vehicle as VehicleType,
242-
Status: 'Activa',
243-
NombreUsuario: userName,
244-
} satisfies ReservationCreate;
245-
246-
const created = await reservationsSvc.create(payload);
247-
248-
// 5) Refrescar listas/estado externo
249-
await opts?.onAfterReserve?.();
250-
251-
const successMsg =
252-
turn === 'Dia'
253-
? `Reserva de día completo creada en celda ${code} para ${dateISO}.`
254-
: `Reserva creada en celda ${code} para ${dateISO} (${turn}).`;
255-
256-
return { ok: true, message: successMsg, reservation: created };
257-
} catch (e) {
258-
console.warn('[useReservar] Falló crear en celda', code, e);
259-
// Si falla con esta celda, intenta con la siguiente
260-
continue;
261-
}
258+
try {
259+
const payload = {
260+
Title: userMail,
261+
Date: dateISO,
262+
Turn: turnValue,
263+
SpotIdLookupId: Number(slotId),
264+
VehicleType: vehicle as VehicleType,
265+
Status: 'Activa',
266+
NombreUsuario: userName,
267+
} satisfies ReservationCreate;
268+
269+
const created = await reservationsSvc.create(payload);
270+
await opts?.onAfterReserve?.();
271+
272+
const successMsg =
273+
turn === 'Dia'
274+
? `Reserva de día completo creada en celda ${code} para ${dateISO}.`
275+
: `Reserva creada en celda ${code} para ${dateISO} (${turn}).`;
276+
277+
return { ok: true, message: successMsg, reservation: created };
278+
} catch (e) {
279+
console.warn('[useReservar] Falló crear en celda', code, e);
280+
continue;
262281
}
263-
264-
// 6) Si ninguna celda tuvo cupo
265-
const turnoTexto = turn === 'Dia' ? 'día completo' : String(turn).toLowerCase();
266-
const msg = `No hay parqueaderos disponibles para ${vehicle} el ${dateISO} en ${turnoTexto}.`;
267-
return { ok: false, message: msg };
268-
},
269-
[
270-
reservationsSvc,
271-
slotsSvc,
272-
hasActiveReservationAnyTurnSameDay,
273-
hasActiveReservationSameDay,
274-
countReservations,
275-
userMail,
276-
userName,
277-
opts,
278-
]
279-
);
282+
}
283+
284+
const turnoTexto = turn === 'Dia' ? 'día completo' : String(turn).toLowerCase();
285+
const msg = `No hay parqueaderos disponibles para ${vehicle} el ${dateISO} en ${turnoTexto}.`;
286+
return { ok: false, message: msg };
287+
},
288+
[
289+
reservationsSvc,
290+
slotsSvc,
291+
hasActiveReservationAnyTurnSameDay,
292+
hasActiveReservationSameDay,
293+
countReservations,
294+
userMail,
295+
userName,
296+
opts,
297+
]
298+
);
280299

281300
return {
282301
minDate,

0 commit comments

Comments
 (0)