import { prisma } from './prisma.js' import type { UnidadCotizable } from './cotizacion.service.js' /** * Espejo local del inventario de unidades (tabla `Unidad`, sembrada por * scripts/seed-unidades-locales.js). Es la única fuente de lectura del * inventario: misma forma de DTO que consumen controllers y fronts. * * La tabla `Unidad` no guarda la fecha de entrega: se completa desde la captura * de obra/escrituración (`CapturaDepartamento`), que es la que llenan los * departamentos. Sin ese dato el cotizador asume el plazo por defecto del * desarrollo (ver DESARROLLOS en cotizacion.service.ts). */ /** * Campos de `CapturaDepartamento` que dan la fecha de entrega de la vivienda, * en orden de prioridad (el primero con fecha válida gana): * 1. `entrega_reprogramada_fecha` — Fecha Reprogramada Entrega (la más reciente, * cuando obra movió la entrega es la fecha que manda) * 2. `entrega_programada_fecha` — Fecha Programada Entrega Vivienda * 3. `habitabilidad` — fecha de habitabilidad (OBRA), la de DIAGONAL * 4. `inicio_obra_fecha` — último recurso (ESCRITURACION) */ export const CAMPOS_FECHA_ENTREGA = [ 'entrega_reprogramada_fecha', 'entrega_programada_fecha', 'habitabilidad', 'inicio_obra_fecha', ] as const /** Normaliza 'YYYY-MM-DD' (o ISO completo); null si el valor no es una fecha usable */ function fechaIso(valor: string | null | undefined): string | null { if (typeof valor !== 'string') return null const fecha = valor.trim().slice(0, 10) return /^\d{4}-\d{2}-\d{2}$/.test(fecha) ? fecha : null } /** Fecha de entrega (ISO) por código de unidad, según la captura de los departamentos */ async function fechasEntregaPorUnidad(codigos?: string[]): Promise> { const filas = await prisma.capturaDepartamento.findMany({ where: { campo: { in: [...CAMPOS_FECHA_ENTREGA] }, ...(codigos ? { unidadCodigo: { in: codigos } } : {}), }, select: { unidadCodigo: true, campo: true, valor: true }, }) const porUnidad = new Map() for (const campo of CAMPOS_FECHA_ENTREGA) { for (const fila of filas) { if (fila.campo !== campo || porUnidad.has(fila.unidadCodigo)) continue const fecha = fechaIso(fila.valor) if (fecha !== null) porUnidad.set(fila.unidadCodigo, fecha) } } return porUnidad } /** Fila de la tabla Unidad tal como la devuelve Prisma (estructural) */ export interface FilaUnidad { codigo: string desarrollo: string modelo: string supConstruccion: number supExcedente: number supEstacionamiento: number precioLista: number precioAcabados: number status: string etapa: string } /** Fila local → DTO `Unidad` (UnidadCotizable) que consumen controllers y fronts */ export function unidadLocalADto(u: FilaUnidad, fechaEntrega: string | null = null): UnidadCotizable { return { codigo: u.codigo, modelo: u.modelo, fechaEntrega, supEstacionamiento: u.supEstacionamiento, supConstruccion: u.supConstruccion, supExcedente: u.supExcedente, precioSinAcabados: u.precioLista, precioConAcabados: u.precioAcabados, status: u.status, desarrollo: u.desarrollo, mesesParaFirma: null, etapa: u.etapa === '' ? null : u.etapa, } } /** Unidades del espejo local; filtros equivalentes a los del controller */ export async function getUnidadesLocal( filtro: { desarrollo?: string | undefined; soloDisponibles?: boolean | undefined } = {}, ): Promise { const rows = await prisma.unidad.findMany({ orderBy: { codigo: 'asc' } }) const fechas = await fechasEntregaPorUnidad() let lista = rows.map((u) => unidadLocalADto(u, fechas.get(u.codigo) ?? null)) if (filtro.soloDisponibles === true) { lista = lista.filter((u) => u.status.trim().toUpperCase() === 'DISPONIBLE') } if (filtro.desarrollo !== undefined && filtro.desarrollo !== '') { const desarrollo = filtro.desarrollo.toUpperCase() lista = lista.filter((u) => (u.desarrollo || 'DIAGONAL').toUpperCase() === desarrollo) } return lista } /** Una unidad local por código; null si no existe en el espejo */ export async function getUnidadLocal(codigo: string): Promise { const row = await prisma.unidad.findUnique({ where: { codigo } }) if (row === null) return null const fechas = await fechasEntregaPorUnidad([codigo]) return unidadLocalADto(row, fechas.get(codigo) ?? null) }