Files
FRASA-CAS/api-gateway/src/services/unidades-local.service.ts

114 lines
4.4 KiB
TypeScript

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<Map<string, string>> {
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<string, string>()
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<UnidadCotizable[]> {
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<UnidadCotizable | null> {
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)
}