socios-comerciales.skyballo.../astro-partner-hub-main/src/lib/api-reservaciones.ts

101 lines
3.4 KiB
TypeScript

// Creación de reservaciones en el backend Lumen (ruta protegida con middleware de socio).
import { apiFetch } from "./api-client";
import { extrasSeleccionados, HORA_CITA, type ReservaEstado } from "./reserva-flujo";
export type ReservacionPayload = {
vuelo_codigo: string;
globo_id: string;
fecha_vuelo: string | null;
fecha_por_confirmar: boolean;
hora_cita: string;
lugar_cita: string;
idioma: string;
adultos: number;
ninos: number;
pasajeros: { nombre: string; apellidos: string; telefono: string; peso: string }[];
extras: { id: string; nombre: string; cantidad: number; precio: number; importe: number }[];
certificados: { nombre: string; frase: string }[];
cupon: string | null;
metodo_pago: string;
subtotal_vuelos: number;
subtotal_extras: number;
descuento: number;
impuestos: number;
total: number;
comision: number;
comision_porcentaje: number;
terminos_aceptados: boolean;
fecha_aceptacion: string;
version_terminos: string;
};
export type ReservacionRespuesta = {
folio?: string;
codigo?: string;
id?: number | string;
message?: string;
data?: { folio?: string; codigo?: string; id?: number | string };
};
export function construirPayloadReservacion(
estado: ReservaEstado,
desglose: {
subtotalVuelos: number;
subtotalExtras: number;
descuento: number;
impuestos: number;
total: number;
},
extra: { comision: number; porcentaje: number; versionTerminos: string },
): ReservacionPayload {
return {
vuelo_codigo: estado.vueloId,
globo_id: estado.globoId,
fecha_vuelo: estado.fechaPorConfirmar ? null : estado.fecha || null,
fecha_por_confirmar: estado.fechaPorConfirmar,
hora_cita: HORA_CITA,
lugar_cita: estado.lugarCita,
idioma: estado.idioma,
adultos: estado.adultos,
ninos: estado.ninos,
pasajeros: estado.pasajeros.map((p) => ({
nombre: p.nombre,
apellidos: p.apellidos,
telefono: p.telefono,
peso: p.peso,
})),
extras: extrasSeleccionados(estado.extras).map((e) => ({
id: e.id,
nombre: e.nombre,
cantidad: e.cantidad,
precio: e.precio,
importe: e.importe,
})),
certificados: estado.certificados.map((c) => ({ nombre: c.nombre, frase: c.frase })),
cupon: estado.cuponCodigo || null,
metodo_pago: estado.metodoPago,
subtotal_vuelos: Math.round(desglose.subtotalVuelos * 100) / 100,
subtotal_extras: Math.round(desglose.subtotalExtras * 100) / 100,
descuento: Math.round(desglose.descuento * 100) / 100,
impuestos: Math.round(desglose.impuestos * 100) / 100,
total: Math.round(desglose.total * 100) / 100,
comision: Math.round(extra.comision * 100) / 100,
comision_porcentaje: extra.porcentaje,
terminos_aceptados: estado.terminosAceptados,
fecha_aceptacion: estado.fechaAceptacion || new Date().toISOString(),
version_terminos: extra.versionTerminos,
};
}
/** POST /reservaciones — devuelve el folio asignado por el backend si existe. */
export async function crearReservacion(payload: ReservacionPayload): Promise<string | null> {
const res = await apiFetch<ReservacionRespuesta>("/reservaciones", {
method: "POST",
auth: true,
body: payload,
mensajeError: "No pudimos registrar la reservación en el sistema.",
});
const folio = res.folio ?? res.codigo ?? res.data?.folio ?? res.data?.codigo ?? res.id ?? res.data?.id;
return folio ? String(folio) : null;
}